-
+ {% if file_exists(imprint) %}
+
+ {% endif %}
+ {% if file_exists(gdpr) %}
+
+
+ {% endif %}
diff --git a/mslib/utils/airdata.py b/mslib/utils/airdata.py
index b7ae556d2..8e0a40157 100644
--- a/mslib/utils/airdata.py
+++ b/mslib/utils/airdata.py
@@ -102,7 +102,7 @@ def get_airports(force_download=False, url=None):
_airports_mtime = Airspace().airports_mtime
if url is None:
- url = "https://ourairports.com/data/airports.csv"
+ url = "https://davidmegginson.github.io/ourairports-data/airports.csv"
file_exists = os.path.exists(os.path.join(OSDIR, "downloads", "aip", "airports.csv"))
@@ -252,7 +252,7 @@ def get_airspaces(countries=None):
for data in airspace_data["polygon"].split(",")]
_airspaces.append(airspace_data)
_airspaces_mtime[file] = os.path.getmtime(os.path.join(OSDIR, "downloads", "aip", file))
- else:
- QtWidgets.QMessageBox.information(None, "No Airspaces data in file:", f"{file}")
+ else:
+ QtWidgets.QMessageBox.information(None, "No Airspaces data in file:", f"{file}")
return _airspaces
diff --git a/mslib/utils/config.py b/mslib/utils/config.py
index c740c220e..af9a918e5 100644
--- a/mslib/utils/config.py
+++ b/mslib/utils/config.py
@@ -111,8 +111,9 @@ class MSUIDefaultConfig:
# URLs of default WMS servers.
default_WMS = [
"http://localhost:8081/",
- "http://eumetview.eumetsat.int/geoserver/wms",
- "https://apps.ecmwf.int/wms/?token=public"
+ "https://view.eumetsat.int/geoserver/wms",
+ "http://eccharts.ecmwf.int/wms/?token=public",
+ "https://neo.gsfc.nasa.gov/wms/wms"
]
default_VSEC_WMS = [
diff --git a/mslib/utils/coordinate.py b/mslib/utils/coordinate.py
index b645fe5ec..54ecb2ff0 100644
--- a/mslib/utils/coordinate.py
+++ b/mslib/utils/coordinate.py
@@ -110,15 +110,13 @@ def rotate_point(point, angle, origin=(0, 0)):
def get_projection_params(proj):
proj = proj.lower()
if proj.startswith("crs:"):
- raise ValueError("CRS not supported")
-
projid = proj[4:]
if projid == "84":
proj_params = {
"basemap": {"projection": "cyl"},
"bbox": "degree"}
else:
- raise ValueError("unsupported CRS code: '%s'", proj)
+ raise ValueError("Only CRS code 84 is supported: '%s' given", proj)
elif proj.startswith("auto:"):
raise ValueError("AUTO not supported")
diff --git a/mslib/utils/time.py b/mslib/utils/time.py
index 00d38f6a2..22b020013 100644
--- a/mslib/utils/time.py
+++ b/mslib/utils/time.py
@@ -43,7 +43,10 @@ def parse_iso_datetime(string):
def parse_iso_duration(string):
- return isodate.parse_duration(string)
+ try:
+ return isodate.parse_duration(string)
+ except isodate.ISO8601Error:
+ return datetime.timedelta(weeks=4)
JSEC_START = datetime.datetime(2000, 1, 1)
diff --git a/mslib/utils/units.py b/mslib/utils/units.py
index 2a6105111..91bc39434 100644
--- a/mslib/utils/units.py
+++ b/mslib/utils/units.py
@@ -99,16 +99,16 @@ def convert_to(value, from_unit, to_unit, default=1.):
value_unit = units.Quantity(value, from_unit)
result = value_unit.to(to_unit).magnitude
except pint.UndefinedUnitError:
- logging.error("Error in unit conversion (undefined) '%s'/'%s'", from_unit, to_unit)
+ logging.warning("Error in unit conversion (undefined) '%s'/'%s'", from_unit, to_unit)
result = value * default
except pint.DimensionalityError:
if units(to_unit).to_base_units().units == units.m:
try:
result = (value_unit / units.Quantity(9.81, "m s^-2")).to(to_unit).magnitude
except pint.DimensionalityError:
- logging.error("Error in unit conversion (dimensionality) %s/%s", from_unit, to_unit)
+ logging.warning("Error in unit conversion (dimensionality) '%s'/'%s'", from_unit, to_unit)
result = value * default
else:
- logging.error("Error in unit conversion (dimensionality) %s/%s", from_unit, to_unit)
+ logging.warning("Error in unit conversion (dimensionality) '%s'/'%s'", from_unit, to_unit)
result = value * default
return result
diff --git a/mslib/version.py b/mslib/version.py
index b2dfa20e9..642cdf5d0 100644
--- a/mslib/version.py
+++ b/mslib/version.py
@@ -24,4 +24,4 @@
See the License for the specific language governing permissions and
limitations under the License.
"""
-__version__ = u'8.2.0'
+__version__ = u'8.3.1'
diff --git a/pytest.ini b/pytest.ini
index 3f0e6d3f9..33d560e1e 100644
--- a/pytest.ini
+++ b/pytest.ini
@@ -6,7 +6,7 @@ log_file = pytest.log
log_file_level = DEBUG
log_file_format = %(asctime)s %(levelname)s %(message)s
log_file_date_format = %Y-%m-%d %H:%M:%S
-timeout = 60
+timeout = 30
filterwarnings =
# These namespaces are declared in a way not conformant with PEP420. Not much we can do about that here, we should keep an eye on when this is fixed in our dependencies though.
ignore:Deprecated call to `pkg_resources.declare_namespace\('(xstatic|xstatic\.pkg|mpl_toolkits|mpl_toolkits\.basemap_data|sphinxcontrib|zope|fs|fs\.opener)'\)`\.:DeprecationWarning
diff --git a/requirements.d/development.txt b/requirements.d/development.txt
index 4a5553df0..e57232b2b 100644
--- a/requirements.d/development.txt
+++ b/requirements.d/development.txt
@@ -23,3 +23,6 @@ pytest-reverse
eventlet>0.30.2
dnspython>=2.0.0, <2.3.0
gsl==2.7.0
+boa
+xmlschema<2.5.0
+
diff --git a/tests/_test_mscolab/test_chat_manager.py b/tests/_test_mscolab/test_chat_manager.py
index 30ceef682..abe1dd2b0 100644
--- a/tests/_test_mscolab/test_chat_manager.py
+++ b/tests/_test_mscolab/test_chat_manager.py
@@ -24,11 +24,14 @@
See the License for the specific language governing permissions and
limitations under the License.
"""
+import os
+import secrets
from flask_testing import TestCase
+from werkzeug.datastructures import FileStorage
from mslib.mscolab.conf import mscolab_settings
-from mslib.mscolab.models import Message, MessageType
+from mslib.mscolab.models import Operation, Message, MessageType
from mslib.mscolab.mscolab import handle_db_reset
from mslib.mscolab.server import APP
from mslib.mscolab.seed import add_user, get_user, add_operation, add_user_to_operation
@@ -89,3 +92,17 @@ def test_delete_messages(self):
self.cm.delete_message(message.id)
message = Message.query.filter(Message.id == message.id).first()
assert message is None
+
+ def test_add_attachment(self):
+ sample_path = os.path.join(os.path.dirname(__file__), "..", "data")
+ filename = "example.csv"
+ name, ext = filename.split('.')
+ open_csv = os.path.join(sample_path, "example.csv")
+ operation = Operation.query.filter_by(path=self.operation_name).first()
+ token = secrets.token_urlsafe(16)
+ with open(open_csv, 'rb') as fp:
+ file = FileStorage(fp, filename=filename, content_type="text/csv")
+ static_path = self.cm.add_attachment(operation.id, mscolab_settings.UPLOAD_FOLDER, file, token)
+ assert name in static_path
+ assert static_path.endswith(ext)
+ assert token in static_path
diff --git a/tests/_test_mscolab/test_file_manager.py b/tests/_test_mscolab/test_file_manager.py
index af41ba37b..11852b27b 100644
--- a/tests/_test_mscolab/test_file_manager.py
+++ b/tests/_test_mscolab/test_file_manager.py
@@ -26,10 +26,11 @@
"""
from flask_testing import TestCase
import os
+import datetime
import pytest
from mslib.mscolab.conf import mscolab_settings
-from mslib.mscolab.models import Operation
+from mslib.mscolab.models import Operation, User
from mslib.mscolab.server import APP
from mslib.mscolab.file_manager import FileManager
from mslib.mscolab.seed import add_user, get_user
@@ -80,7 +81,40 @@ def setUp(self):
def tearDown(self):
pass
- @pytest.mark.skip(reason="needs review for py311")
+ def test_modify_user(self):
+ with self.app.test_client():
+ user = User("user@example.com", "user", "password")
+ assert user.id is None
+ assert User.query.filter_by(emailid=user.emailid).first() is None
+ # creeat the user
+ self.fm.modify_user(user, action="create")
+ user_query = User.query.filter_by(emailid=user.emailid).first()
+ assert user_query.id is not None
+ assert user_query is not None
+ assert user_query.confirmed is False
+ # cannot create a user a second time
+ assert self.fm.modify_user(user, action="create") is False
+ # confirming the user
+ confirm_time = datetime.datetime.now() + datetime.timedelta(days=1)
+ self.fm.modify_user(user_query, attribute="confirmed_on", value=confirm_time)
+ self.fm.modify_user(user_query, attribute="confirmed", value=True)
+ user_query = User.query.filter_by(id=user.id).first()
+ assert user_query.confirmed is True
+ assert user_query.confirmed_on == confirm_time
+ assert user_query.confirmed_on > user_query.registered_on
+ # deleting the user
+ self.fm.modify_user(user_query, action="delete")
+ user_query = User.query.filter_by(id=user_query.id).first()
+ assert user_query is None
+
+ def test_modify_user_special_cases(self):
+ user1 = User("user1@example.com", "user1", "password")
+ user2 = User("user2@example.com", "user2", "password")
+ self.fm.modify_user(user1, action="create")
+ self.fm.modify_user(user2, action="create")
+ user_query1 = User.query.filter_by(emailid=user1.emailid).first()
+ assert self.fm.modify_user(user_query1, "emailid", user2.emailid) is False
+
def test_fetch_operation_creator(self):
with self.app.test_client():
flight_path, operation = self._create_operation(flight_path="more_than_one")
@@ -204,11 +238,10 @@ def test_update_operation(self):
assert ren_operation.id == operation.id
assert ren_operation.path == rename_to
- def test_delete_file(self):
- # Todo rename "file" to operation
+ def test_delete_operation(self):
with self.app.test_client():
flight_path, operation = self._create_operation(flight_path='operation4')
- assert self.fm.delete_file(operation.id, self.user)
+ assert self.fm.delete_operation(operation.id, self.user)
assert Operation.query.filter_by(path=flight_path).first() is None
def test_get_authorized_users(self):
@@ -245,7 +278,7 @@ def test_get_change_content(self):
assert self.fm.save_file(operation.id, self.content1, self.user)
assert self.fm.save_file(operation.id, self.content2, self.user)
all_changes = self.fm.get_all_changes(operation.id, self.user)
- assert self.fm.get_change_content(all_changes[1]["id"]) == self.content1
+ assert self.fm.get_change_content(all_changes[1]["id"], self.user) == self.content1
def test_set_version_name(self):
with self.app.test_client():
@@ -273,15 +306,15 @@ def test_undo(self):
assert self.fm.save_file(operation.id, self.content2, self.user)
all_changes = self.fm.get_all_changes(operation.id, self.user)
# crestor
- assert self.fm.undo(all_changes[1]["id"], self.user)
+ assert self.fm.undo_changes(all_changes[1]["id"], self.user)
# check collaborator
self.fm.add_bulk_permission(operation.id, self.user, [self.collaboratoruser.id], "collaborator")
assert self.fm.is_collaborator(self.collaboratoruser.id, operation.id)
- assert self.fm.undo(all_changes[1]["id"], self.collaboratoruser)
+ assert self.fm.undo_changes(all_changes[1]["id"], self.collaboratoruser)
# check viewer
self.fm.add_bulk_permission(operation.id, self.user, [self.vieweruser.id], "viewer")
assert self.fm.is_viewer(self.vieweruser.id, operation.id)
- assert self.fm.undo(all_changes[1]["id"], self.vieweruser) is False
+ assert self.fm.undo_changes(all_changes[1]["id"], self.vieweruser) is False
def test_fetch_users_without_permission(self):
with self.app.test_client():
diff --git a/tests/_test_mscolab/test_files.py b/tests/_test_mscolab/test_files.py
index 6db498a21..df774e02f 100644
--- a/tests/_test_mscolab/test_files.py
+++ b/tests/_test_mscolab/test_files.py
@@ -129,7 +129,7 @@ def test_undo(self):
changes = Change.query.filter_by(op_id=operation.id).all()
assert changes is not None
assert changes[0].id == 1
- assert self.fm.undo(changes[0].id, self.user) is True
+ assert self.fm.undo_changes(changes[0].id, self.user) is True
assert len(self.fm.get_all_changes(operation.id, self.user)) == 3
assert "beta" in self.fm.get_file(operation.id, self.user)
@@ -162,9 +162,9 @@ def test_delete_operation(self):
with self.app.test_client():
self._create_operation(flight_path="f3")
op_id = get_recent_op_id(self.fm, self.user)
- assert self.fm.delete_file(op_id, self.user2) is False
- assert self.fm.delete_file(op_id, self.user) is True
- assert self.fm.delete_file(op_id, self.user) is False
+ assert self.fm.delete_operation(op_id, self.user2) is False
+ assert self.fm.delete_operation(op_id, self.user) is True
+ assert self.fm.delete_operation(op_id, self.user) is False
permissions = Permission.query.filter_by(op_id=op_id).all()
assert len(permissions) == 0
operations_db = Operation.query.filter_by(id=op_id).all()
diff --git a/tests/_test_mscolab/test_files_api.py b/tests/_test_mscolab/test_files_api.py
index 0aeb89473..1ac772f6f 100644
--- a/tests/_test_mscolab/test_files_api.py
+++ b/tests/_test_mscolab/test_files_api.py
@@ -182,12 +182,11 @@ def test_update_operation(self):
operation = Operation.query.filter_by(path=new_flight_path).first()
assert operation.description == new_description
- def test_delete_file(self):
- # ToDo rename to operation
+ def test_delete_operation(self):
with self.app.test_client():
flight_path, operation = self._create_operation(flight_path="V10")
assert operation.path == flight_path
- assert self.fm.delete_file(operation.id, self.user)
+ assert self.fm.delete_operation(operation.id, self.user)
operation = Operation.query.filter_by(path=flight_path).first()
assert operation is None
@@ -206,9 +205,9 @@ def test_get_change_content(self):
assert self.fm.save_file(operation.id, "content2", self.user)
assert self.fm.save_file(operation.id, "content3", self.user)
all_changes = self.fm.get_all_changes(operation.id, self.user)
- previous_change = self.fm.get_change_content(all_changes[2]["id"])
+ previous_change = self.fm.get_change_content(all_changes[2]["id"], self.user)
assert previous_change == "content1"
- previous_change = self.fm.get_change_content(all_changes[1]["id"])
+ previous_change = self.fm.get_change_content(all_changes[1]["id"], self.user)
assert previous_change == "content2"
def test_set_version_name(self):
diff --git a/tests/_test_mscolab/test_server.py b/tests/_test_mscolab/test_server.py
index 1d6bc4882..c1bd4b460 100644
--- a/tests/_test_mscolab/test_server.py
+++ b/tests/_test_mscolab/test_server.py
@@ -88,13 +88,13 @@ def test_register_user(self):
assert result["success"] is True
result = register_user(self.userdata[0], self.userdata[1], self.userdata[2])
assert result["success"] is False
- assert result["message"] == "Oh no, this email ID is already taken!"
+ assert result["message"] == "This email ID is already taken!"
result = register_user("UV", self.userdata[1], self.userdata[2])
assert result["success"] is False
- assert result["message"] == "Oh no, your email ID is not valid!"
+ assert result["message"] == "Your email ID is not valid!"
result = register_user(self.userdata[0], self.userdata[1], self.userdata[0])
assert result["success"] is False
- assert result["message"] == "Oh no, your username cannot contain @ symbol!"
+ assert result["message"] == "Your username cannot contain @ symbol!"
def test_check_login(self):
with self.app.test_client():
@@ -149,11 +149,11 @@ def test_delete_user(self):
assert add_user(self.userdata[0], self.userdata[1], self.userdata[2])
with self.app.test_client() as test_client:
token = self._get_token(test_client, self.userdata)
- response = test_client.post('/delete_user', data={"token": token})
+ response = test_client.post('/delete_own_account', data={"token": token})
assert response.status_code == 200
data = json.loads(response.data.decode('utf-8'))
assert data["success"] is True
- response = test_client.post('/delete_user', data={"token": "dsdsds"})
+ response = test_client.post('/delete_own_account', data={"token": "dsdsds"})
assert response.status_code == 200
assert response.data.decode('utf-8') == "False"
@@ -348,15 +348,6 @@ def test_set_last_used(self):
data = json.loads(response.data.decode('utf-8'))
assert data["success"] is True
- def test_update_last_used(self):
- assert add_user(self.userdata[0], self.userdata[1], self.userdata[2])
- with self.app.test_client() as test_client:
- operation, token = self._create_operation(test_client, self.userdata)
- response = test_client.post('/update_last_used', data={"token": token})
- assert response.status_code == 200
- data = json.loads(response.data.decode('utf-8'))
- assert data["success"] is True
-
def test_get_users_without_permission(self):
assert add_user(self.userdata[0], self.userdata[1], self.userdata[2])
unprevileged_user = 'UV20@uv20', 'UV20', 'uv20'
diff --git a/tests/_test_msui/test_kmloverlay_dockwidget.py b/tests/_test_msui/test_kmloverlay_dockwidget.py
index 130197436..d3eaf43a7 100644
--- a/tests/_test_msui/test_kmloverlay_dockwidget.py
+++ b/tests/_test_msui/test_kmloverlay_dockwidget.py
@@ -37,6 +37,8 @@
save_kml = os.path.join(ROOT_DIR, "merged_file123.kml")
+# ToDo refactoring, extract helper methods into functions
+# ToDo review needed helper functions
class Test_KmlOverlayDockWidget(object):
def setup_method(self):
@@ -70,6 +72,7 @@ def select_file(self, file): # Utility function for single file
path = fs.path.join(sample_path, file)
filename = (path,) # converted to tuple
self.window.select_file(filename)
+ self.window.load_file()
QtWidgets.QApplication.processEvents()
return path
@@ -103,7 +106,7 @@ def test_select_file(self, mockbox):
assert mockbox.critical.call_count == 0
assert self.window.listWidget.count() == index
assert len(self.window.dict_files) == index
- assert self.count_patches() > 0
+ assert self.count_patches() == 9
self.window.select_all()
self.window.remove_file()
@@ -118,6 +121,7 @@ def test_select_file_error(self, mockbox):
path = fs.path.join(sample_path, "satellite_predictor.txt")
filename = (path,) # converted to tuple
self.window.select_file(filename)
+ self.window.load_file()
QtWidgets.QApplication.processEvents()
assert mockbox.critical.call_count == 1
self.window.listWidget.clear()
diff --git a/tests/_test_msui/test_mscolab.py b/tests/_test_msui/test_mscolab.py
index 80b399ab6..6065c4475 100644
--- a/tests/_test_msui/test_mscolab.py
+++ b/tests/_test_msui/test_mscolab.py
@@ -38,7 +38,7 @@
from mslib.mscolab.models import Permission, User
from mslib.msui.flighttrack import WaypointsTableModel
from PyQt5 import QtCore, QtTest, QtWidgets
-from mslib.utils.config import read_config_file, config_loader
+from mslib.utils.config import read_config_file, config_loader, modify_config_file
from tests.utils import mscolab_start_server, create_msui_settings_file, ExceptionMock
from mslib.msui import msui
from mslib.msui import mscolab
@@ -64,6 +64,7 @@ def setup_method(self):
QtTest.QTest.qWait(500)
self.application = QtWidgets.QApplication(sys.argv)
self.main_window = msui.MSUIMainWindow(mscolab_data_dir=mscolab_settings.MSCOLAB_DATA_DIR)
+ self.main_window.create_new_flight_track()
self.main_window.show()
self.window = mscolab.MSColab_ConnectDialog(parent=self.main_window, mscolab=self.main_window.mscolab)
self.window.urlCb.setEditText(self.url)
@@ -115,15 +116,37 @@ def test_connect_success(self, mockbox, mockset):
def test_disconnect(self):
self._connect_to_mscolab()
assert self.window.mscolab_server_url is not None
- QtTest.QTest.mouseClick(self.window.connectBtn, QtCore.Qt.LeftButton)
+ QtTest.QTest.mouseClick(self.window.disconnectBtn, QtCore.Qt.LeftButton)
assert self.window.mscolab_server_url is None
# set ui_name_winodw default
assert self.main_window.usernameLabel.text() == 'User'
def test_login(self):
self._connect_to_mscolab()
+ modify_config_file({"MSS_auth": {self.url: self.userdata[0]}})
+ self._login(self.userdata[0], self.userdata[2])
+ QtWidgets.QApplication.processEvents()
+ # show logged in widgets
+ assert self.main_window.usernameLabel.text() == self.userdata[1]
+ assert self.main_window.connectBtn.isVisible() is False
+ assert self.main_window.mscolab.connect_window is None
+ assert self.main_window.local_active is True
+ # test operation listing visibility
+ assert self.main_window.listOperationsMSC.model().rowCount() == 1
+
+ @mock.patch("PyQt5.QtWidgets.QMessageBox.question", return_value=QtWidgets.QMessageBox.Yes)
+ def test_login_with_different_account_shows_update_credentials_popup(self, mockbox):
+ self._connect_to_mscolab()
+ connect_window = self.main_window.mscolab.connect_window
self._login(self.userdata[0], self.userdata[2])
QtWidgets.QApplication.processEvents()
+ mockbox.assert_called_once_with(
+ connect_window,
+ "Update Credentials",
+ "You are using new credentials. Should your settings file be updated with the new credentials?",
+ mock.ANY,
+ mock.ANY,
+ )
# show logged in widgets
assert self.main_window.usernameLabel.text() == self.userdata[1]
assert self.main_window.connectBtn.isVisible() is False
@@ -135,6 +158,7 @@ def test_login(self):
def test_logout_action_trigger(self):
# Login
self._connect_to_mscolab()
+ modify_config_file({"MSS_auth": {self.url: self.userdata[0]}})
self._login(self.userdata[0], self.userdata[2])
QtWidgets.QApplication.processEvents()
assert self.main_window.usernameLabel.text() == self.userdata[1]
@@ -149,6 +173,7 @@ def test_logout_action_trigger(self):
def test_logout(self):
# Login
self._connect_to_mscolab()
+ modify_config_file({"MSS_auth": {self.url: self.userdata[0]}})
self._login(self.userdata[0], self.userdata[2])
QtWidgets.QApplication.processEvents()
assert self.main_window.usernameLabel.text() == self.userdata[1]
@@ -163,6 +188,7 @@ def test_logout(self):
@mock.patch("PyQt5.QtWidgets.QMessageBox.question", return_value=QtWidgets.QMessageBox.Yes)
def test_add_user(self, mockmessage):
self._connect_to_mscolab()
+ modify_config_file({"MSS_auth": {self.url: "something@something.org"}})
self._create_user("something", "something@something.org", "something")
assert config_loader(dataset="MSS_auth").get(self.url) == "something@something.org"
assert mslib.utils.auth.get_password_from_keyring("MSCOLAB",
@@ -197,6 +223,7 @@ def test_add_users_with_updating_credentials_in_config_file(self, mockmessage):
assert config_loader(dataset="MSS_auth").get(self.url) == "something@something.org"
self._connect_to_mscolab()
assert self.window.mscolab_server_url is not None
+ modify_config_file({"MSS_auth": {self.url: "anand@something.org"}})
self._create_user("anand", "anand@something.org", "anand_pass")
# check changed settings
assert config_loader(dataset="MSS_auth").get(self.url) == "anand@something.org"
@@ -246,8 +273,8 @@ class Test_Mscolab(object):
sample_path = os.path.join(os.path.dirname(__file__), "..", "data")
# import/export plugins
import_plugins = {
- "Text": ["txt", "mslib.plugins.io.text", "load_from_txt"],
- "FliteStar": ["fls", "mslib.plugins.io.flitestar", "load_from_flitestar"],
+ "TXT": ["txt", "mslib.plugins.io.text", "load_from_txt"],
+ "FliteStar": ["txt", "mslib.plugins.io.flitestar", "load_from_flitestar"],
}
export_plugins = {
"Text": ["txt", "mslib.plugins.io.text", "save_to_txt"],
@@ -277,6 +304,7 @@ def setup_method(self):
QtTest.QTest.qWait(500)
self.application = QtWidgets.QApplication(sys.argv)
self.window = msui.MSUIMainWindow(mscolab_data_dir=mscolab_settings.MSCOLAB_DATA_DIR)
+ self.window.create_new_flight_track()
self.window.show()
def teardown_method(self):
@@ -296,6 +324,7 @@ def teardown_method(self):
def test_activate_operation(self):
self._connect_to_mscolab()
+ modify_config_file({"MSS_auth": {self.url: self.userdata[0]}})
self._login(emailid=self.userdata[0], password=self.userdata[2])
# activate a operation
self._activate_operation_at_index(0)
@@ -305,6 +334,7 @@ def test_activate_operation(self):
@mock.patch("PyQt5.QtWidgets.QMessageBox")
def test_view_open(self, mockbox):
self._connect_to_mscolab()
+ modify_config_file({"MSS_auth": {self.url: self.userdata[0]}})
self._login(emailid=self.userdata[0], password=self.userdata[2])
# test after activating operation
self._activate_operation_at_index(0)
@@ -338,6 +368,7 @@ def test_view_open(self, mockbox):
"Flight track (*.ftml)"))
def test_handle_export(self, mockbox):
self._connect_to_mscolab()
+ modify_config_file({"MSS_auth": {self.url: self.userdata[0]}})
self._login(emailid=self.userdata[0], password=self.userdata[2])
self._activate_operation_at_index(0)
self.window.actionExportFlightTrackFTML.trigger()
@@ -349,50 +380,36 @@ def test_handle_export(self, mockbox):
for i in range(wp_count):
assert exported_waypoints.waypoint_data(i).lat == self.window.mscolab.waypoints_model.waypoint_data(i).lat
- @pytest.mark.skip("fails on github with WebSocket transport is not available")
- @pytest.mark.parametrize("ext", [".ftml", ".csv", ".txt"])
+ @pytest.mark.parametrize("name", [("example.ftml", "actionImportFlightTrackFTML", 5),
+ ("example.csv", "actionImportFlightTrackCSV", 5),
+ ("example.txt", "actionImportFlightTrackTXT", 5),
+ ("flitestar.txt", "actionImportFlightTrackFliteStar", 10)])
@mock.patch("PyQt5.QtWidgets.QMessageBox")
- def test_import_file(self, mockbox, ext):
+ def test_import_file(self, mockbox, name):
self.window.remove_plugins()
with mock.patch("mslib.msui.msui_mainwindow.config_loader", return_value=self.import_plugins):
self.window.add_import_plugins("qt")
- with mock.patch("mslib.msui.msui_mainwindow.config_loader", return_value=self.export_plugins):
- self.window.add_export_plugins("qt")
- file_path = fs.path.join(mscolab_settings.MSCOLAB_DATA_DIR, f'test_import{ext}')
- with mock.patch("PyQt5.QtWidgets.QFileDialog.getSaveFileName", return_value=(file_path, None)):
- with mock.patch("PyQt5.QtWidgets.QFileDialog.getOpenFileName", return_value=(file_path, None)):
- self._connect_to_mscolab()
- self._login(emailid=self.userdata[0], password=self.userdata[2])
- self._activate_operation_at_index(0)
- exported_wp = WaypointsTableModel(waypoints=self.window.mscolab.waypoints_model.waypoints)
- full_name = f"actionExportFlightTrack{ext[1:]}"
- for action in self.window.menuExportActiveFlightTrack.actions():
- if action.objectName() == full_name:
- action.trigger()
- break
- assert os.path.exists(fs.path.join(mscolab_settings.MSCOLAB_DATA_DIR, f'test_import{ext}'))
- QtWidgets.QApplication.processEvents()
- self.window.mscolab.waypoints_model.invert_direction()
- QtWidgets.QApplication.processEvents()
- QtTest.QTest.qWait(100)
- assert exported_wp.waypoint_data(0).lat != self.window.mscolab.waypoints_model.waypoint_data(0).lat
- full_name = f"actionImportFlightTrack{ext[1:]}"
- for action in self.window.menuImportFlightTrack.actions():
- if action.objectName() == full_name:
- action.trigger()
- break
- QtWidgets.QApplication.processEvents()
- QtTest.QTest.qWait(100)
- assert len(self.window.mscolab.waypoints_model.waypoints) == 2
- imported_wp = self.window.mscolab.waypoints_model
- wp_count = len(imported_wp.waypoints)
- assert wp_count == 2
- for i in range(wp_count):
- assert exported_wp.waypoint_data(i).lat == imported_wp.waypoint_data(i).lat
+ file_path = fs.path.join(self.sample_path, name[0])
+ with mock.patch("mslib.msui.msui_mainwindow.get_open_filenames", return_value=[file_path]) as mockopen:
+ # with parametrize it is maybe too fast
+ QtTest.QTest.qWait(100)
+ self._connect_to_mscolab()
+ self._login(emailid=self.userdata[0], password=self.userdata[2])
+ self._activate_operation_at_index(0)
+ wp = self.window.mscolab.waypoints_model
+ assert len(wp.waypoints) == 2
+ for action in self.window.menuImportFlightTrack.actions():
+ if action.objectName() == name[1]:
+ action.trigger()
+ break
+ assert mockopen.call_count == 1
+ imported_wp = self.window.mscolab.waypoints_model
+ assert len(imported_wp.waypoints) == name[2]
@pytest.mark.skip("Runs in a timeout locally > 60s")
def test_work_locally_toggle(self):
self._connect_to_mscolab()
+ modify_config_file({"MSS_auth": {self.url: self.userdata[0]}})
self._login(emailid=self.userdata[0], password=self.userdata[2])
self._activate_operation_at_index(0)
self.window.workLocallyCheckbox.setChecked(True)
@@ -413,6 +430,7 @@ def test_work_locally_toggle(self):
@mock.patch("mslib.msui.mscolab.get_open_filename", return_value=os.path.join(sample_path, u"example.ftml"))
def test_browse_add_operation(self, mockopen, mockmessage):
self._connect_to_mscolab()
+ modify_config_file({"MSS_auth": {self.url: "something@something.org"}})
self._create_user("something", "something@something.org", "something")
assert self.window.listOperationsMSC.model().rowCount() == 0
self.window.actionAddOperation.trigger()
@@ -436,59 +454,75 @@ def test_browse_add_operation(self, mockopen, mockmessage):
assert item.operation_path == "example"
assert item.access_level == "creator"
- @mock.patch("PyQt5.QtWidgets.QErrorMessage")
- def test_add_operation(self, mockbox):
+ def test_add_operation(self):
self._connect_to_mscolab()
+ modify_config_file({"MSS_auth": {self.url: "something@something.org"}})
self._create_user("something", "something@something.org", "something")
assert self.window.usernameLabel.text() == 'something'
assert self.window.connectBtn.isVisible() is False
- self._create_operation("Alpha", "Description Alpha")
- assert mockbox.return_value.showMessage.call_count == 1
- with mock.patch("PyQt5.QtWidgets.QLineEdit.text", return_value=None):
+ with mock.patch("PyQt5.QtWidgets.QMessageBox.information", return_value=QtWidgets.QMessageBox.Ok) as m:
+ self._create_operation("Alpha", "Description Alpha")
+ m.assert_called_once_with(
+ self.window,
+ "Creation successful",
+ "Your operation was created successfully.",
+ )
+ with (mock.patch("PyQt5.QtWidgets.QLineEdit.text", return_value=None),
+ mock.patch("PyQt5.QtWidgets.QErrorMessage.showMessage") as m):
self._create_operation("Alpha2", "Description Alpha")
- with mock.patch("PyQt5.QtWidgets.QTextEdit.toPlainText", return_value=None):
+ m.assert_called_once_with("Path can't be empty")
+ with (mock.patch("PyQt5.QtWidgets.QTextEdit.toPlainText", return_value=None),
+ mock.patch("PyQt5.QtWidgets.QErrorMessage.showMessage") as m):
self._create_operation("Alpha3", "Description Alpha")
- self._create_operation("/", "Description Alpha")
- assert mockbox.return_value.showMessage.call_count == 4
+ m.assert_called_once_with("Description can't be empty")
+ with mock.patch("PyQt5.QtWidgets.QErrorMessage.showMessage") as m:
+ self._create_operation("/", "Description Alpha")
+ m.assert_called_once_with("Path can't contain spaces or special characters")
assert self.window.listOperationsMSC.model().rowCount() == 1
- self._create_operation("reproduce-test", "Description Test")
+ with mock.patch("PyQt5.QtWidgets.QMessageBox.information", return_value=QtWidgets.QMessageBox.Ok) as m:
+ self._create_operation("reproduce-test", "Description Test")
+ m.assert_called_once()
assert self.window.listOperationsMSC.model().rowCount() == 2
self._activate_operation_at_index(0)
assert self.window.mscolab.active_operation_name == "Alpha"
self._activate_operation_at_index(1)
assert self.window.mscolab.active_operation_name == "reproduce-test"
- @pytest.mark.skip(reason="needs review for py311")
- @mock.patch("PyQt5.QtWidgets.QMessageBox.information")
@mock.patch("PyQt5.QtWidgets.QInputDialog.getText", return_value=("flight7", True))
- def test_handle_delete_operation(self, mocktext, mockbox):
+ def test_handle_delete_operation(self, mocktext):
+ # pytest.skip('needs a review for the delete button pressed. Seems to delete a None operation')
self._connect_to_mscolab()
+ modify_config_file({"MSS_auth": {self.url: "berta@something.org"}})
self._create_user("berta", "berta@something.org", "something")
assert self.window.usernameLabel.text() == 'berta'
assert self.window.connectBtn.isVisible() is False
assert self.window.listOperationsMSC.model().rowCount() == 0
operation_name = "flight7"
- self._create_operation(operation_name, "Description flight7")
+ with mock.patch("PyQt5.QtWidgets.QMessageBox.information", return_value=QtWidgets.QMessageBox.Ok) as m:
+ self._create_operation(operation_name, "Description flight7")
+ m.assert_called_once()
# check for operation dir is created on server
assert os.path.isdir(os.path.join(mscolab_settings.MSCOLAB_DATA_DIR, operation_name))
self._activate_operation_at_index(0)
op_id = self.window.mscolab.get_recent_op_id()
assert op_id is not None
assert self.window.listOperationsMSC.model().rowCount() == 1
- self.window.actionDeleteOperation.trigger()
- QtWidgets.QApplication.processEvents()
+ with mock.patch("PyQt5.QtWidgets.QMessageBox.information", return_value=QtWidgets.QMessageBox.Ok) as m:
+ self.window.actionDeleteOperation.trigger()
+ QtWidgets.QApplication.processEvents()
+ m.assert_called_once_with(self.window, "Success", 'Operation "flight7" was deleted!')
op_id = self.window.mscolab.get_recent_op_id()
assert op_id is None
QtWidgets.QApplication.processEvents()
QtTest.QTest.qWait(0)
# check operation dir name removed
assert os.path.isdir(os.path.join(mscolab_settings.MSCOLAB_DATA_DIR, operation_name)) is False
- assert mockbox.call_count == 1
@mock.patch("PyQt5.QtWidgets.QMessageBox.question", return_value=QtWidgets.QMessageBox.Yes)
def test_handle_leave_operation(self, mockmessage):
self._connect_to_mscolab()
+ modify_config_file({"MSS_auth": {self.url: self.userdata3[0]}})
self._login(self.userdata3[0], self.userdata3[2])
QtWidgets.QApplication.processEvents()
assert self.window.usernameLabel.text() == self.userdata3[1]
@@ -514,56 +548,68 @@ def test_handle_leave_operation(self, mockmessage):
assert self.window.listViews.count() == 0
assert self.window.listOperationsMSC.model().rowCount() == 0
- @mock.patch("PyQt5.QtWidgets.QMessageBox.information")
@mock.patch("PyQt5.QtWidgets.QInputDialog.getText", return_value=("new_name", True))
- def test_handle_rename_operation(self, mockbox, mockpatch):
+ def test_handle_rename_operation(self, mocktext):
self._connect_to_mscolab()
+ modify_config_file({"MSS_auth": {self.url: "something@something.org"}})
self._create_user("something", "something@something.org", "something")
- self._create_operation("flight1234", "Description flight1234")
+ with mock.patch("PyQt5.QtWidgets.QMessageBox.information", return_value=QtWidgets.QMessageBox.Ok) as m:
+ self._create_operation("flight1234", "Description flight1234")
+ m.assert_called_once()
assert self.window.listOperationsMSC.model().rowCount() == 1
self._activate_operation_at_index(0)
assert self.window.mscolab.active_op_id is not None
- self.window.actionRenameOperation.trigger()
- QtWidgets.QApplication.processEvents()
+ with mock.patch("PyQt5.QtWidgets.QMessageBox.information", return_value=QtWidgets.QMessageBox.Ok) as m:
+ self.window.actionRenameOperation.trigger()
+ QtWidgets.QApplication.processEvents()
+ m.assert_called_once_with(self.window, "Rename successful", "Operation is renamed successfully.")
QtTest.QTest.qWait(0)
assert self.window.mscolab.active_op_id is not None
assert self.window.mscolab.active_operation_name == "new_name"
- @pytest.mark.skip(reason="needs review for py311")
- @mock.patch("PyQt5.QtWidgets.QMessageBox.information")
- @mock.patch("PyQt5.QtWidgets.QInputDialog.getText", return_value=("new_desciption", True))
- def test_update_description(self, mockbox, mockpatch):
+ @mock.patch("PyQt5.QtWidgets.QInputDialog.getText", return_value=("new_description", True))
+ def test_update_description(self, mocktext):
self._connect_to_mscolab()
+ modify_config_file({"MSS_auth": {self.url: "something@something.org"}})
self._create_user("something", "something@something.org", "something")
- self._create_operation("flight1234", "Description flight1234")
+ with mock.patch("PyQt5.QtWidgets.QMessageBox.information", return_value=QtWidgets.QMessageBox.Ok) as m:
+ self._create_operation("flight1234", "Description flight1234")
+ m.assert_called_once()
assert self.window.listOperationsMSC.model().rowCount() == 1
self._activate_operation_at_index(0)
assert self.window.mscolab.active_op_id is not None
- self.window.actionChangeDescription.trigger()
- QtWidgets.QApplication.processEvents()
+ with mock.patch("PyQt5.QtWidgets.QMessageBox.information", return_value=QtWidgets.QMessageBox.Ok) as m:
+ self.window.actionChangeDescription.trigger()
+ QtWidgets.QApplication.processEvents()
+ m.assert_called_once_with(self.window, "Update successful", "Description is updated successfully.")
QtTest.QTest.qWait(0)
assert self.window.mscolab.active_op_id is not None
- assert self.window.mscolab.active_operation_description == "new_desciption"
+ assert self.window.mscolab.active_operation_description == "new_description"
- @mock.patch("PyQt5.QtWidgets.QMessageBox.information")
@mock.patch("PyQt5.QtWidgets.QInputDialog.getText", return_value=("new_category", True))
- def test_update_category(self, mockbox, mockpatch):
+ def test_update_category(self, mocktext):
self._connect_to_mscolab()
+ modify_config_file({"MSS_auth": {self.url: "something@something.org"}})
self._create_user("something", "something@something.org", "something")
- self._create_operation("flight1234", "Description flight1234")
+ with mock.patch("PyQt5.QtWidgets.QMessageBox.information", return_value=QtWidgets.QMessageBox.Ok) as m:
+ self._create_operation("flight1234", "Description flight1234")
+ m.assert_called_once()
assert self.window.listOperationsMSC.model().rowCount() == 1
assert self.window.mscolab.active_operation_category == "example"
self._activate_operation_at_index(0)
assert self.window.mscolab.active_op_id is not None
- self.window.actionChangeCategory.trigger()
- QtWidgets.QApplication.processEvents()
+ with mock.patch("PyQt5.QtWidgets.QMessageBox.information", return_value=QtWidgets.QMessageBox.Ok) as m:
+ self.window.actionChangeCategory.trigger()
+ QtWidgets.QApplication.processEvents()
+ m.assert_called_once_with(self.window, "Update successful", "Category is updated successfully.")
QtTest.QTest.qWait(0)
assert self.window.mscolab.active_op_id is not None
assert self.window.mscolab.active_operation_category == "new_category"
@mock.patch("PyQt5.QtWidgets.QMessageBox.information")
- def test_any_special_category(self, mockpatch):
+ def test_any_special_category(self, mockbox):
self._connect_to_mscolab()
+ modify_config_file({"MSS_auth": {self.url: "something@something.org"}})
self._create_user("something", "something@something.org", "something")
self._create_operation("flight1234", "Description flight1234")
QtTest.QTest.qWait(0)
@@ -581,8 +627,10 @@ def test_any_special_category(self, mockpatch):
range(self.window.mscolab.ui.listOperationsMSC.count())]
assert ["flight5678"] == operation_pathes
- def test_get_recent_op_id(self):
+ @mock.patch("PyQt5.QtWidgets.QMessageBox.information", return_value=QtWidgets.QMessageBox.Ok)
+ def test_get_recent_op_id(self, mockbox):
self._connect_to_mscolab()
+ modify_config_file({"MSS_auth": {self.url: "anton@something.org"}})
self._create_user("anton", "anton@something.org", "something")
QtTest.QTest.qWait(100)
assert self.window.usernameLabel.text() == 'anton'
@@ -595,8 +643,10 @@ def test_get_recent_op_id(self):
# ToDo fix number after cleanup initial data
assert self.window.mscolab.get_recent_op_id() == current_op_id + 2
- def test_get_recent_operation(self):
+ @mock.patch("PyQt5.QtWidgets.QMessageBox.information", return_value=QtWidgets.QMessageBox.Ok)
+ def test_get_recent_operation(self, mockbox):
self._connect_to_mscolab()
+ modify_config_file({"MSS_auth": {self.url: "berta@something.org"}})
self._create_user("berta", "berta@something.org", "something")
QtTest.QTest.qWait(100)
assert self.window.usernameLabel.text() == 'berta'
@@ -608,8 +658,10 @@ def test_get_recent_operation(self):
assert operation["path"] == "flight1234"
assert operation["access_level"] == "creator"
- def test_open_chat_window(self):
+ @mock.patch("PyQt5.QtWidgets.QMessageBox.information", return_value=QtWidgets.QMessageBox.Ok)
+ def test_open_chat_window(self, mockbox):
self._connect_to_mscolab()
+ modify_config_file({"MSS_auth": {self.url: "something@something.org"}})
self._create_user("something", "something@something.org", "something")
self._create_operation("flight1234", "Description flight1234")
assert self.window.listOperationsMSC.model().rowCount() == 1
@@ -620,9 +672,10 @@ def test_open_chat_window(self):
QtTest.QTest.qWait(0)
assert self.window.mscolab.chat_window is not None
- @pytest.mark.skip(reason="needs review for py311")
- def test_close_chat_window(self):
+ @mock.patch("PyQt5.QtWidgets.QMessageBox.information", return_value=QtWidgets.QMessageBox.Ok)
+ def test_close_chat_window(self, mockbox):
self._connect_to_mscolab()
+ modify_config_file({"MSS_auth": {self.url: "something@something.org"}})
self._create_user("something", "something@something.org", "something")
self._create_operation("flight1234", "Description flight1234")
assert self.window.listOperationsMSC.model().rowCount() == 1
@@ -633,9 +686,10 @@ def test_close_chat_window(self):
self.window.mscolab.close_chat_window()
assert self.window.mscolab.chat_window is None
- @pytest.mark.skip("py.311, needs review")
- def test_delete_operation_from_list(self):
+ @mock.patch("PyQt5.QtWidgets.QMessageBox.information", return_value=QtWidgets.QMessageBox.Ok)
+ def test_delete_operation_from_list(self, mockbox):
self._connect_to_mscolab()
+ modify_config_file({"MSS_auth": {self.url: "other@something.org"}})
self._create_user("other", "other@something.org", "something")
assert self.window.usernameLabel.text() == 'other'
assert self.window.connectBtn.isVisible() is False
@@ -650,6 +704,7 @@ def test_delete_operation_from_list(self):
@mock.patch("PyQt5.QtWidgets.QMessageBox.question", return_value=QtWidgets.QMessageBox.Yes)
def test_user_delete(self, mockmessage):
self._connect_to_mscolab()
+ modify_config_file({"MSS_auth": {self.url: "something@something.org"}})
self._create_user("something", "something@something.org", "something")
u_id = self.window.mscolab.user['id']
self.window.mscolab.open_profile_window()
@@ -696,6 +751,7 @@ def test_create_dir_exceptions(self, mockexit, mockbox):
@mock.patch("PyQt5.QtWidgets.QMessageBox")
def test_profile_dialog(self, mockbox):
self._connect_to_mscolab()
+ modify_config_file({"MSS_auth": {self.url: "something@something.org"}})
self._create_user("something", "something@something.org", "something")
self.window.mscolab.profile_action.trigger()
QtWidgets.QApplication.processEvents()
@@ -743,8 +799,7 @@ def _reset_config_file(self):
config_file = fs.path.combine(MSUI_CONFIG_PATH, "msui_settings.json")
read_config_file(path=config_file)
- @mock.patch("mslib.msui.mscolab.QtWidgets.QErrorMessage.showMessage")
- def _create_operation(self, path, description, mockbox, category="example"):
+ def _create_operation(self, path, description, category="example"):
self.window.actionAddOperation.trigger()
QtWidgets.QApplication.processEvents()
self.window.mscolab.add_proj_dialog.path.setText(str(path))
diff --git a/tests/_test_msui/test_mscolab_admin_window.py b/tests/_test_msui/test_mscolab_admin_window.py
index 4427d3083..348c17814 100644
--- a/tests/_test_msui/test_mscolab_admin_window.py
+++ b/tests/_test_msui/test_mscolab_admin_window.py
@@ -25,6 +25,7 @@
limitations under the License.
"""
import os
+import mock
import pytest
import sys
@@ -35,6 +36,7 @@
from mslib.msui import msui
from mslib.mscolab.mscolab import handle_db_reset
from mslib.mscolab.seed import add_user, get_user, add_operation, add_user_to_operation
+from mslib.utils.config import modify_config_file
PORTS = list(range(24000, 24500))
@@ -68,9 +70,11 @@ def setup_method(self):
QtTest.QTest.qWait(500)
self.application = QtWidgets.QApplication(sys.argv)
self.window = msui.MSUIMainWindow(mscolab_data_dir=mscolab_settings.MSCOLAB_DATA_DIR)
+ self.window.create_new_flight_track()
self.window.show()
# connect and login to mscolab
self._connect_to_mscolab()
+ modify_config_file({"MSS_auth": {self.url: self.userdata[0]}})
self._login(emailid=self.userdata[0], password=self.userdata[2])
# activate operation and open chat window
self._activate_operation_at_index(0)
@@ -86,6 +90,9 @@ def teardown_method(self):
self.window.mscolab.admin_window.close()
if self.window.mscolab.conn:
self.window.mscolab.conn.disconnect()
+ with mock.patch("PyQt5.QtWidgets.QMessageBox.warning", return_value=QtWidgets.QMessageBox.Yes):
+ self.window.close()
+ QtWidgets.QApplication.processEvents()
self.application.quit()
QtWidgets.QApplication.processEvents()
self.process.terminate()
diff --git a/tests/_test_msui/test_mscolab_merge_waypoints.py b/tests/_test_msui/test_mscolab_merge_waypoints.py
index 6ac974510..e8afee9fc 100644
--- a/tests/_test_msui/test_mscolab_merge_waypoints.py
+++ b/tests/_test_msui/test_mscolab_merge_waypoints.py
@@ -53,6 +53,7 @@ def setup_method(self):
QtTest.QTest.qWait(500)
self.application = QtWidgets.QApplication(sys.argv)
self.window = msui.MSUIMainWindow(mscolab_data_dir=mscolab_settings.MSCOLAB_DATA_DIR)
+ self.window.create_new_flight_track()
self.emailid = 'merge@alpha.org'
def teardown_method(self):
diff --git a/tests/_test_msui/test_mscolab_operation.py b/tests/_test_msui/test_mscolab_operation.py
index 5ca3a48dd..ec2b769a9 100644
--- a/tests/_test_msui/test_mscolab_operation.py
+++ b/tests/_test_msui/test_mscolab_operation.py
@@ -36,6 +36,7 @@
from mslib.msui import msui
from mslib.mscolab.mscolab import handle_db_reset
from mslib.mscolab.seed import add_user, get_user, add_operation, add_user_to_operation
+from mslib.utils.config import modify_config_file
PORTS = list(range(22000, 22500))
@@ -63,9 +64,11 @@ def setup_method(self):
QtTest.QTest.qWait(500)
self.application = QtWidgets.QApplication(sys.argv)
self.window = msui.MSUIMainWindow(mscolab_data_dir=mscolab_settings.MSCOLAB_DATA_DIR)
+ self.window.create_new_flight_track()
self.window.show()
# connect and login to mscolab
self._connect_to_mscolab()
+ modify_config_file({"MSS_auth": {self.url: self.userdata[0]}})
self._login(self.userdata[0], self.userdata[2])
# activate operation and open chat window
self._activate_operation_at_index(0)
diff --git a/tests/_test_msui/test_mscolab_version_history.py b/tests/_test_msui/test_mscolab_version_history.py
index 01e48739f..7d4a33b4c 100644
--- a/tests/_test_msui/test_mscolab_version_history.py
+++ b/tests/_test_msui/test_mscolab_version_history.py
@@ -36,6 +36,7 @@
from mslib.msui import msui
from mslib.mscolab.mscolab import handle_db_reset
from mslib.mscolab.seed import add_user, get_user, add_operation, add_user_to_operation
+from mslib.utils.config import modify_config_file
PORTS = list(range(20000, 20500))
@@ -56,9 +57,11 @@ def setup_method(self):
QtTest.QTest.qWait(500)
self.application = QtWidgets.QApplication(sys.argv)
self.window = msui.MSUIMainWindow(mscolab_data_dir=mscolab_settings.MSCOLAB_DATA_DIR)
+ self.window.create_new_flight_track()
self.window.show()
# connect and login to mscolab
self._connect_to_mscolab()
+ modify_config_file({"MSS_auth": {self.url: self.userdata[0]}})
self._login(self.userdata[0], self.userdata[2])
# activate operation and open chat window
self._activate_operation_at_index(0)
@@ -113,7 +116,7 @@ def test_version_name_delete(self, mockbox):
assert self.version_window.changes.currentItem().version_name is None
@mock.patch("PyQt5.QtWidgets.QMessageBox.question", return_value=QtWidgets.QMessageBox.Yes)
- def test_undo(self, mockbox):
+ def test_undo_changes(self, mockbox):
self._change_version_filter(1)
# make changes
for i in range(2):
diff --git a/tests/_test_msui/test_msui.py b/tests/_test_msui/test_msui.py
index c423bbb20..d31556bce 100644
--- a/tests/_test_msui/test_msui.py
+++ b/tests/_test_msui/test_msui.py
@@ -29,6 +29,7 @@
import sys
import mock
import os
+import fs
import platform
import argparse
import pytest
@@ -139,7 +140,7 @@ class Test_MSSSideViewWindow(object):
save_txt = os.path.join(ROOT_DIR, "example.txt")
# import/export plugins
import_plugins = {
- "Text": ["txt", "mslib.plugins.io.text", "load_from_txt"],
+ "TXT": ["txt", "mslib.plugins.io.text", "load_from_txt"],
"FliteStar": ["txt", "mslib.plugins.io.flitestar", "load_from_flitestar"],
}
export_plugins = {
@@ -258,24 +259,24 @@ def test_plugin_saveas(self, save_file):
assert os.path.exists(save_file[0])
os.remove(save_file[0])
- @pytest.mark.parametrize(
- "open_file", [(open_ftml, "actionImportFlightTrackFTML"),
- (open_txt, "actionImportFlightTrackText"), (open_fls, "actionImportFlightTrackFliteStar")])
- def test_plugin_import(self, open_file):
+ @pytest.mark.parametrize("name", [("example.ftml", "actionImportFlightTrackFTML", 5),
+ ("example.csv", "actionImportFlightTrackCSV", 5),
+ ("example.txt", "actionImportFlightTrackTXT", 5),
+ ("flitestar.txt", "actionImportFlightTrackFliteStar", 10)])
+ def test_plugin_import(self, name):
with mock.patch("mslib.msui.msui_mainwindow.config_loader", return_value=self.import_plugins):
self.window.add_import_plugins("qt")
- with mock.patch("mslib.msui.msui_mainwindow.get_open_filenames", return_value=open_file) as mockopen:
- assert self.window.listFlightTracks.count() == 1
- assert mockopen.call_count == 0
- self.window.last_save_directory = ROOT_DIR
- obj_name = open_file[1]
+ assert self.window.listFlightTracks.count() == 1
+ file_path = fs.path.join(self.sample_path, name[0])
+ with mock.patch("mslib.msui.msui_mainwindow.get_open_filenames", return_value=[file_path]) as mockopen:
for action in self.window.menuImportFlightTrack.actions():
- if obj_name == action.objectName():
+ if action.objectName() == name[1]:
action.trigger()
break
- QtWidgets.QApplication.processEvents()
assert mockopen.call_count == 1
assert self.window.listFlightTracks.count() == 2
+ assert self.window.active_flight_track.name == name[0].split(".")[0]
+ assert len(self.window.active_flight_track.waypoints) == name[2]
@pytest.mark.parametrize("save_file", [[save_ftml, "actionExportFlightTrackFTML"],
[save_txt, "actionExportFlightTrackText"]])
diff --git a/tests/_test_msui/test_multiple_flightpath_dockwidget.py b/tests/_test_msui/test_multiple_flightpath_dockwidget.py
index aac22bb3f..9d824ced1 100644
--- a/tests/_test_msui/test_multiple_flightpath_dockwidget.py
+++ b/tests/_test_msui/test_multiple_flightpath_dockwidget.py
@@ -46,7 +46,8 @@ def setup_method(self):
self.waypoints_model = ft.WaypointsTableModel("myname")
self.waypoints_model.insertRows(
0, rows=len(initial_waypoints), waypoints=initial_waypoints)
- self.widget = tv.MSUITopViewWindow(parent=self.window, model=self.waypoints_model)
+
+ self.widget = tv.MSUITopViewWindow(model=self.waypoints_model, mainwindow=self.window)
self.window.show()
QtWidgets.QApplication.processEvents()
QtTest.QTest.qWaitForWindowExposed(self.window)
@@ -59,5 +60,6 @@ def teardown_method(self):
QtWidgets.QApplication.processEvents()
def test_initialization(self):
- widget = MultipleFlightpathControlWidget(parent=self.widget, listFlightTracks=self.widget.ui.listFlightTracks)
+ widget = MultipleFlightpathControlWidget(parent=self.widget,
+ listFlightTracks=self.window.listFlightTracks)
assert widget.color == (0, 0, 1, 1)
diff --git a/tests/_test_msui/test_satellite_dockwidget.py b/tests/_test_msui/test_satellite_dockwidget.py
index e558fcd1c..8ebbf7c84 100644
--- a/tests/_test_msui/test_satellite_dockwidget.py
+++ b/tests/_test_msui/test_satellite_dockwidget.py
@@ -61,7 +61,13 @@ def test_load(self):
assert self.view.plot_satellite_overpass.call_count == 2
self.view.reset_mock()
- def test_load_no_file(self):
+ @mock.patch("PyQt5.QtWidgets.QMessageBox.critical")
+ def test_load_no_file(self, mockbox):
QtTest.QTest.mouseClick(self.window.btLoadFile, QtCore.Qt.LeftButton)
QtWidgets.QApplication.processEvents()
assert self.window.cbSatelliteOverpasses.count() == 0
+ mockbox.assert_called_once_with(
+ self.window,
+ "Satellite Overpass Tool",
+ "ERROR:\n
\npath '' should be a file",
+ )
diff --git a/tests/_test_msui/test_topview.py b/tests/_test_msui/test_topview.py
index 2f1c3d84d..e0539e841 100644
--- a/tests/_test_msui/test_topview.py
+++ b/tests/_test_msui/test_topview.py
@@ -32,10 +32,11 @@
import sys
import multiprocessing
import tempfile
+import mslib.msui.topview as tv
from mslib.mswms.mswms import application
from PyQt5 import QtWidgets, QtCore, QtTest
from mslib.msui import flighttrack as ft
-import mslib.msui.topview as tv
+from mslib.msui.msui import MSUIMainWindow
from mslib.msui.mpl_qtwidget import _DEFAULT_SETTINGS_TOPVIEW
from tests.utils import wait_until_signal
@@ -70,12 +71,13 @@ def test_get(self, mockcrit):
class Test_MSSTopViewWindow(object):
def setup_method(self):
+ mainwindow = MSUIMainWindow()
self.application = QtWidgets.QApplication(sys.argv)
initial_waypoints = [ft.Waypoint(40., 25., 0), ft.Waypoint(60., -10., 0), ft.Waypoint(40., 10, 0)]
waypoints_model = ft.WaypointsTableModel("")
waypoints_model.insertRows(
0, rows=len(initial_waypoints), waypoints=initial_waypoints)
- self.window = tv.MSUITopViewWindow(model=waypoints_model)
+ self.window = tv.MSUITopViewWindow(model=waypoints_model, mainwindow=mainwindow)
self.window.show()
QtWidgets.QApplication.processEvents()
QtTest.QTest.qWaitForWindowExposed(self.window)
@@ -312,7 +314,8 @@ def setup_method(self):
waypoints_model.insertRows(
0, rows=len(initial_waypoints), waypoints=initial_waypoints)
- self.window = tv.MSUITopViewWindow(model=waypoints_model)
+ mainwindow = MSUIMainWindow()
+ self.window = tv.MSUITopViewWindow(model=waypoints_model, mainwindow=mainwindow)
self.window.show()
QtWidgets.QApplication.processEvents()
QtTest.QTest.qWait(2000)
@@ -364,7 +367,8 @@ def test_kwargs_update_does_not_harm(self):
initial_waypoints = [ft.Waypoint(40., 25., 0), ft.Waypoint(60., -10., 0), ft.Waypoint(40., 10, 0)]
waypoints_model = ft.WaypointsTableModel("")
waypoints_model.insertRows(0, rows=len(initial_waypoints), waypoints=initial_waypoints)
- self.window = tv.MSUITopViewWindow(model=waypoints_model)
+ mainwindow = MSUIMainWindow()
+ self.window = tv.MSUITopViewWindow(model=waypoints_model, mainwindow=mainwindow)
# user_options is a global var
from mslib.utils.config import user_options
diff --git a/tests/_test_utils/test_airdata.py b/tests/_test_utils/test_airdata.py
index 6da4a94fc..837ee250b 100644
--- a/tests/_test_utils/test_airdata.py
+++ b/tests/_test_utils/test_airdata.py
@@ -206,10 +206,12 @@ def test_get_airspaces(mockbox):
@mock.patch("mslib.utils.airdata.download_progress", _download_incomplete_airspace)
+@mock.patch("PyQt5.QtWidgets.QMessageBox.information")
@mock.patch("PyQt5.QtWidgets.QMessageBox.question", return_value=QtWidgets.QMessageBox.Yes)
-def test_get_airspaces_missing_data(mockbox):
+def test_get_airspaces_missing_data(mockbox, infobox):
""" We use a test file without the need for downloading to check handling """
# update_airspace would only update after 30 days
_cleanup_test_files()
airspaces = get_airspaces(countries=["bg"])
assert airspaces == []
+ infobox.assert_called_once_with(None, 'No Airspaces data in file:', 'bg_asp.xml')
diff --git a/tests/_test_utils/test_coordinate.py b/tests/_test_utils/test_coordinate.py
index 5408ce48c..e38582aeb 100644
--- a/tests/_test_utils/test_coordinate.py
+++ b/tests/_test_utils/test_coordinate.py
@@ -60,7 +60,7 @@ def test_get_projection_params(self):
with pytest.raises(ValueError):
coordinate.get_projection_params('auto:42001')
with pytest.raises(ValueError):
- coordinate.get_projection_params('crs:84')
+ coordinate.get_projection_params('crs:83')
class TestAngles(object):
diff --git a/tests/utils.py b/tests/utils.py
index 895dca650..d2a07be3c 100644
--- a/tests/utils.py
+++ b/tests/utils.py
@@ -41,6 +41,7 @@
from mslib.mscolab.conf import mscolab_settings
from mslib.mscolab.server import APP, initialize_managers, start_server
from mslib.mscolab.mscolab import handle_db_init
+from mslib.utils.config import modify_config_file
def callback_ok_image(status, response_headers):
@@ -106,7 +107,7 @@ def mscolab_delete_user(app, msc_url, email, password):
response = mscolab_login(app, msc_url, email, password)
if response.status == '200 OK':
data = json.loads(response.get_data(as_text=True))
- url = urljoin(msc_url, 'delete_user')
+ url = urljoin(msc_url, 'delete_own_account')
response = app.test_client().post(url, data=data)
if response.status == '200 OK':
data = json.loads(response.get_data(as_text=True))
@@ -198,6 +199,9 @@ def mscolab_start_server(all_ports, mscolab_settings=mscolab_settings, timeout=1
url = f"http://localhost:{port}"
+ # Update mscolab URL to avoid "Update Server List" message boxes
+ modify_config_file({"default_MSCOLAB": [url]})
+
_app = APP
_app.config['SQLALCHEMY_DATABASE_URI'] = mscolab_settings.SQLALCHEMY_DB_URI
_app.config['MSCOLAB_DATA_DIR'] = mscolab_settings.MSCOLAB_DATA_DIR