STAR-322: Mocking the CuraApp

This commit is contained in:
Daniel Schiavini 2018-12-17 14:41:28 +01:00
parent 3b367938de
commit 75d7d49349
6 changed files with 238 additions and 73 deletions

View file

@ -52,7 +52,7 @@ class CloudApiClient:
def getClusters(self, on_finished: Callable[[List[CloudClusterResponse]], Any]) -> None: def getClusters(self, on_finished: Callable[[List[CloudClusterResponse]], Any]) -> None:
url = "{}/clusters".format(self.CLUSTER_API_ROOT) url = "{}/clusters".format(self.CLUSTER_API_ROOT)
reply = self._manager.get(self._createEmptyRequest(url)) reply = self._manager.get(self._createEmptyRequest(url))
self._addCallbacks(reply, on_finished, CloudClusterResponse) self._addCallback(reply, on_finished, CloudClusterResponse)
## Retrieves the status of the given cluster. ## Retrieves the status of the given cluster.
# \param cluster_id: The ID of the cluster. # \param cluster_id: The ID of the cluster.
@ -60,7 +60,7 @@ class CloudApiClient:
def getClusterStatus(self, cluster_id: str, on_finished: Callable[[CloudClusterStatus], Any]) -> None: def getClusterStatus(self, cluster_id: str, on_finished: Callable[[CloudClusterStatus], Any]) -> None:
url = "{}/clusters/{}/status".format(self.CLUSTER_API_ROOT, cluster_id) url = "{}/clusters/{}/status".format(self.CLUSTER_API_ROOT, cluster_id)
reply = self._manager.get(self._createEmptyRequest(url)) reply = self._manager.get(self._createEmptyRequest(url))
self._addCallbacks(reply, on_finished, CloudClusterStatus) self._addCallback(reply, on_finished, CloudClusterStatus)
## Requests the cloud to register the upload of a print job mesh. ## Requests the cloud to register the upload of a print job mesh.
# \param request: The request object. # \param request: The request object.
@ -70,7 +70,7 @@ class CloudApiClient:
url = "{}/jobs/upload".format(self.CURA_API_ROOT) url = "{}/jobs/upload".format(self.CURA_API_ROOT)
body = json.dumps({"data": request.toDict()}) body = json.dumps({"data": request.toDict()})
reply = self._manager.put(self._createEmptyRequest(url), body.encode()) reply = self._manager.put(self._createEmptyRequest(url), body.encode())
self._addCallbacks(reply, on_finished, CloudPrintJobResponse) self._addCallback(reply, on_finished, CloudPrintJobResponse)
## Requests the cloud to register the upload of a print job mesh. ## Requests the cloud to register the upload of a print job mesh.
# \param upload_response: The object received after requesting an upload with `self.requestUpload`. # \param upload_response: The object received after requesting an upload with `self.requestUpload`.
@ -90,7 +90,7 @@ class CloudApiClient:
def requestPrint(self, cluster_id: str, job_id: str, on_finished: Callable[[CloudPrintResponse], Any]) -> None: def requestPrint(self, cluster_id: str, job_id: str, on_finished: Callable[[CloudPrintResponse], Any]) -> None:
url = "{}/clusters/{}/print/{}".format(self.CLUSTER_API_ROOT, cluster_id, job_id) url = "{}/clusters/{}/print/{}".format(self.CLUSTER_API_ROOT, cluster_id, job_id)
reply = self._manager.post(self._createEmptyRequest(url), b"") reply = self._manager.post(self._createEmptyRequest(url), b"")
self._addCallbacks(reply, on_finished, CloudPrintResponse) self._addCallback(reply, on_finished, CloudPrintResponse)
## We override _createEmptyRequest in order to add the user credentials. ## We override _createEmptyRequest in order to add the user credentials.
# \param url: The URL to request # \param url: The URL to request
@ -147,7 +147,7 @@ class CloudApiClient:
# \param on_finished: The callback in case the response is successful. # \param on_finished: The callback in case the response is successful.
# \param model: The type of the model to convert the response to. It may either be a single record or a list. # \param model: The type of the model to convert the response to. It may either be a single record or a list.
# \return: A function that can be passed to the # \return: A function that can be passed to the
def _addCallbacks(self, def _addCallback(self,
reply: QNetworkReply, reply: QNetworkReply,
on_finished: Union[Callable[[Model], Any], Callable[[List[Model]], Any]], on_finished: Union[Callable[[Model], Any], Callable[[List[Model]], Any]],
model: Type[Model], model: Type[Model],

View file

@ -6,7 +6,6 @@ from typing import List
from unittest import TestCase from unittest import TestCase
from unittest.mock import patch, MagicMock from unittest.mock import patch, MagicMock
from cura.CuraApplication import CuraApplication
from cura.CuraConstants import CuraCloudAPIRoot from cura.CuraConstants import CuraCloudAPIRoot
from src.Cloud.CloudApiClient import CloudApiClient from src.Cloud.CloudApiClient import CloudApiClient
from src.Cloud.Models.CloudClusterResponse import CloudClusterResponse from src.Cloud.Models.CloudClusterResponse import CloudClusterResponse
@ -29,7 +28,6 @@ class TestCloudApiClient(TestCase):
self.account = MagicMock() self.account = MagicMock()
self.account.isLoggedIn.return_value = True self.account.isLoggedIn.return_value = True
self.app = CuraApplication.getInstance()
self.network = NetworkManagerMock() self.network = NetworkManagerMock()
with patch("src.Cloud.CloudApiClient.QNetworkAccessManager", return_value = self.network): with patch("src.Cloud.CloudApiClient.QNetworkAccessManager", return_value = self.network):
self.api = CloudApiClient(self.account, self._errorHandler) self.api = CloudApiClient(self.account, self._errorHandler)

View file

@ -30,9 +30,13 @@ class TestCloudOutputDevice(TestCase):
def setUp(self): def setUp(self):
super().setUp() super().setUp()
self.app = CuraApplication.getInstance() self.app = MagicMock()
self.backend = MagicMock(backendStateChange = Signal())
self.app.setBackend(self.backend) self.patches = [patch("UM.Qt.QtApplication.QtApplication.getInstance", return_value=self.app),
patch("UM.Application.Application.getInstance", return_value=self.app)]
for patched_method in self.patches:
patched_method.start()
self.cluster = CloudClusterResponse(self.CLUSTER_ID, self.HOST_GUID, self.HOST_NAME, is_online=True, self.cluster = CloudClusterResponse(self.CLUSTER_ID, self.HOST_GUID, self.HOST_NAME, is_online=True,
status="active") status="active")
@ -41,6 +45,7 @@ class TestCloudOutputDevice(TestCase):
self.onError = MagicMock() self.onError = MagicMock()
with patch("src.Cloud.CloudApiClient.QNetworkAccessManager", return_value = self.network): with patch("src.Cloud.CloudApiClient.QNetworkAccessManager", return_value = self.network):
self._api = CloudApiClient(self.account, self.onError) self._api = CloudApiClient(self.account, self.onError)
self.device = CloudOutputDevice(self._api, self.cluster) self.device = CloudOutputDevice(self._api, self.cluster)
self.cluster_status = parseFixture("getClusterStatusResponse") self.cluster_status = parseFixture("getClusterStatusResponse")
self.network.prepareReply("GET", self.STATUS_URL, 200, readFixture("getClusterStatusResponse")) self.network.prepareReply("GET", self.STATUS_URL, 200, readFixture("getClusterStatusResponse"))
@ -48,6 +53,8 @@ class TestCloudOutputDevice(TestCase):
def tearDown(self): def tearDown(self):
super().tearDown() super().tearDown()
self.network.flushReplies() self.network.flushReplies()
for patched_method in self.patches:
patched_method.stop()
def test_status(self): def test_status(self):
self.device._update() self.device._update()
@ -105,9 +112,8 @@ class TestCloudOutputDevice(TestCase):
self.network.flushReplies() self.network.flushReplies()
self.assertEqual([], self.device.printers) self.assertEqual([], self.device.printers)
@patch("cura.CuraApplication.CuraApplication.getGlobalContainerStack") def test_print_to_cloud(self):
def test_print_to_cloud(self, global_container_stack_mock): active_machine_mock = self.app.getGlobalContainerStack.return_value
active_machine_mock = global_container_stack_mock.return_value
active_machine_mock.getMetaDataEntry.side_effect = {"file_formats": "application/gzip"}.get active_machine_mock.getMetaDataEntry.side_effect = {"file_formats": "application/gzip"}.get
request_upload_response = parseFixture("putJobUploadResponse") request_upload_response = parseFixture("putJobUploadResponse")

View file

@ -1,14 +1,14 @@
# Copyright (c) 2018 Ultimaker B.V. # Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher. # Cura is released under the terms of the LGPLv3 or higher.
from unittest import TestCase from unittest import TestCase
from unittest.mock import patch from unittest.mock import patch, MagicMock
from cura.CuraApplication import CuraApplication from UM.OutputDevice.OutputDeviceManager import OutputDeviceManager
from cura.CuraConstants import CuraCloudAPIRoot from cura.CuraConstants import CuraCloudAPIRoot
from src.Cloud.CloudOutputDevice import CloudOutputDevice from src.Cloud.CloudOutputDevice import CloudOutputDevice
from src.Cloud.CloudOutputDeviceManager import CloudOutputDeviceManager from src.Cloud.CloudOutputDeviceManager import CloudOutputDeviceManager
from tests.Cloud.Fixtures import parseFixture, readFixture from tests.Cloud.Fixtures import parseFixture, readFixture
from .NetworkManagerMock import NetworkManagerMock from .NetworkManagerMock import NetworkManagerMock, FakeSignal
class TestCloudOutputDeviceManager(TestCase): class TestCloudOutputDeviceManager(TestCase):
@ -18,9 +18,19 @@ class TestCloudOutputDeviceManager(TestCase):
def setUp(self): def setUp(self):
super().setUp() super().setUp()
self.app = CuraApplication.getInstance() self.app = MagicMock()
self.device_manager = OutputDeviceManager()
self.app.getOutputDeviceManager.return_value = self.device_manager
self.patches = [patch("UM.Qt.QtApplication.QtApplication.getInstance", return_value=self.app),
patch("UM.Application.Application.getInstance", return_value=self.app)]
for patched_method in self.patches:
patched_method.start()
self.network = NetworkManagerMock() self.network = NetworkManagerMock()
with patch("src.Cloud.CloudApiClient.QNetworkAccessManager", return_value = self.network): self.timer = MagicMock(timeout = FakeSignal())
with patch("src.Cloud.CloudApiClient.QNetworkAccessManager", return_value = self.network), \
patch("src.Cloud.CloudOutputDeviceManager.QTimer", return_value = self.timer):
self.manager = CloudOutputDeviceManager() self.manager = CloudOutputDeviceManager()
self.clusters_response = parseFixture("getClusters") self.clusters_response = parseFixture("getClusters")
self.network.prepareReply("GET", self.URL, 200, readFixture("getClusters")) self.network.prepareReply("GET", self.URL, 200, readFixture("getClusters"))
@ -28,7 +38,11 @@ class TestCloudOutputDeviceManager(TestCase):
def tearDown(self): def tearDown(self):
try: try:
self._beforeTearDown() self._beforeTearDown()
self.network.flushReplies()
self.manager.stop() self.manager.stop()
for patched_method in self.patches:
patched_method.stop()
finally: finally:
super().tearDown() super().tearDown()
@ -38,8 +52,7 @@ class TestCloudOutputDeviceManager(TestCase):
# let the network send replies # let the network send replies
self.network.flushReplies() self.network.flushReplies()
# get the created devices # get the created devices
device_manager = self.app.getOutputDeviceManager() devices = self.device_manager.getOutputDevices()
devices = device_manager.getOutputDevices()
# get the server data # get the server data
clusters = self.clusters_response.get("data", []) clusters = self.clusters_response.get("data", [])
self.assertEqual([CloudOutputDevice] * len(clusters), [type(d) for d in devices]) self.assertEqual([CloudOutputDevice] * len(clusters), [type(d) for d in devices])
@ -48,13 +61,12 @@ class TestCloudOutputDeviceManager(TestCase):
key=lambda device_dict: device_dict["host_version"])) key=lambda device_dict: device_dict["host_version"]))
for device in clusters: for device in clusters:
device_manager.getOutputDevice(device["cluster_id"]).close() self.device_manager.getOutputDevice(device["cluster_id"]).close()
device_manager.removeOutputDevice(device["cluster_id"]) self.device_manager.removeOutputDevice(device["cluster_id"])
## Runs the initial request to retrieve the clusters. ## Runs the initial request to retrieve the clusters.
def _loadData(self): def _loadData(self):
self.manager.start() self.manager.start()
self.manager._onLoginStateChanged(is_logged_in = True)
self.network.flushReplies() self.network.flushReplies()
def test_device_is_created(self): def test_device_is_created(self):
@ -79,22 +91,20 @@ class TestCloudOutputDeviceManager(TestCase):
self.manager._update_timer.timeout.emit() self.manager._update_timer.timeout.emit()
@patch("cura.CuraApplication.CuraApplication.getGlobalContainerStack") def test_device_connects_by_cluster_id(self):
def test_device_connects_by_cluster_id(self, global_container_stack_mock): active_machine_mock = self.app.getGlobalContainerStack.return_value
active_machine_mock = global_container_stack_mock.return_value
cluster1, cluster2 = self.clusters_response["data"] cluster1, cluster2 = self.clusters_response["data"]
cluster_id = cluster1["cluster_id"] cluster_id = cluster1["cluster_id"]
active_machine_mock.getMetaDataEntry.side_effect = {"um_cloud_cluster_id": cluster_id}.get active_machine_mock.getMetaDataEntry.side_effect = {"um_cloud_cluster_id": cluster_id}.get
self._loadData() self._loadData()
self.assertTrue(self.app.getOutputDeviceManager().getOutputDevice(cluster1["cluster_id"]).isConnected()) self.assertTrue(self.device_manager.getOutputDevice(cluster1["cluster_id"]).isConnected())
self.assertFalse(self.app.getOutputDeviceManager().getOutputDevice(cluster2["cluster_id"]).isConnected()) self.assertFalse(self.device_manager.getOutputDevice(cluster2["cluster_id"]).isConnected())
self.assertEquals([], active_machine_mock.setMetaDataEntry.mock_calls) self.assertEquals([], active_machine_mock.setMetaDataEntry.mock_calls)
@patch("cura.CuraApplication.CuraApplication.getGlobalContainerStack") def test_device_connects_by_network_key(self):
def test_device_connects_by_network_key(self, global_container_stack_mock): active_machine_mock = self.app.getGlobalContainerStack.return_value
active_machine_mock = global_container_stack_mock.return_value
cluster1, cluster2 = self.clusters_response["data"] cluster1, cluster2 = self.clusters_response["data"]
network_key = cluster2["host_name"] + ".ultimaker.local" network_key = cluster2["host_name"] + ".ultimaker.local"
@ -102,8 +112,9 @@ class TestCloudOutputDeviceManager(TestCase):
self._loadData() self._loadData()
self.assertFalse(self.app.getOutputDeviceManager().getOutputDevice(cluster1["cluster_id"]).isConnected()) self.assertEqual([False, True],
self.assertTrue(self.app.getOutputDeviceManager().getOutputDevice(cluster2["cluster_id"]).isConnected()) [self.device_manager.getOutputDevice(cluster["cluster_id"]).isConnected()
for cluster in (cluster1, cluster2)])
active_machine_mock.setMetaDataEntry.assert_called_with("um_cloud_cluster_id", cluster2["cluster_id"]) active_machine_mock.setMetaDataEntry.assert_called_with("um_cloud_cluster_id", cluster2["cluster_id"])

View file

@ -0,0 +1,190 @@
# Copyright (c) 2018 Ultimaker B.V.
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
import io
import json
from unittest import TestCase, mock
from unittest.mock import patch, call
from PyQt5.QtCore import QByteArray
from UM.MimeTypeDatabase import MimeType
from UM.Application import Application
from plugins.UM3NetworkPrinting.src.SendMaterialJob import SendMaterialJob
@patch("builtins.open", lambda _, __: io.StringIO("<xml></xml>"))
@patch("UM.MimeTypeDatabase.MimeTypeDatabase.getMimeTypeForFile",
lambda _: MimeType(name = "application/x-ultimaker-material-profile", comment = "Ultimaker Material Profile",
suffixes = ["xml.fdm_material"]))
@patch("UM.Resources.Resources.getAllResourcesOfType", lambda _: ["/materials/generic_pla_white.xml.fdm_material"])
@patch("plugins.UM3NetworkPrinting.src.ClusterUM3OutputDevice")
@patch("PyQt5.QtNetwork.QNetworkReply")
class TestSendMaterialJob(TestCase):
_LOCAL_MATERIAL_WHITE = {"type": "material", "status": "unknown", "id": "generic_pla_white",
"base_file": "generic_pla_white", "setting_version": "5", "name": "White PLA",
"brand": "Generic", "material": "PLA", "color_name": "White",
"GUID": "badb0ee7-87c8-4f3f-9398-938587b67dce", "version": "1", "color_code": "#ffffff",
"description": "Test PLA White", "adhesion_info": "Use glue.", "approximate_diameter": "3",
"properties": {"density": "1.00", "diameter": "2.85", "weight": "750"},
"definition": "fdmprinter", "compatible": True}
_LOCAL_MATERIAL_BLACK = {"type": "material", "status": "unknown", "id": "generic_pla_black",
"base_file": "generic_pla_black", "setting_version": "5", "name": "Yellow CPE",
"brand": "Ultimaker", "material": "CPE", "color_name": "Black",
"GUID": "5fbb362a-41f9-4818-bb43-15ea6df34aa4", "version": "1", "color_code": "#000000",
"description": "Test PLA Black", "adhesion_info": "Use glue.", "approximate_diameter": "3",
"properties": {"density": "1.01", "diameter": "2.85", "weight": "750"},
"definition": "fdmprinter", "compatible": True}
_REMOTE_MATERIAL_WHITE = {
"guid": "badb0ee7-87c8-4f3f-9398-938587b67dce",
"material": "PLA",
"brand": "Generic",
"version": 1,
"color": "White",
"density": 1.00
}
_REMOTE_MATERIAL_BLACK = {
"guid": "5fbb362a-41f9-4818-bb43-15ea6df34aa4",
"material": "PLA",
"brand": "Generic",
"version": 2,
"color": "Black",
"density": 1.00
}
def test_run(self, device_mock, reply_mock):
job = SendMaterialJob(device_mock)
job.run()
# We expect the materials endpoint to be called when the job runs.
device_mock.get.assert_called_with("materials/", on_finished = job._onGetRemoteMaterials)
def test__onGetRemoteMaterials_withFailedRequest(self, reply_mock, device_mock):
reply_mock.attribute.return_value = 404
job = SendMaterialJob(device_mock)
job._onGetRemoteMaterials(reply_mock)
# We expect the device not to be called for any follow up.
self.assertEqual(0, device_mock.createFormPart.call_count)
def test__onGetRemoteMaterials_withWrongEncoding(self, reply_mock, device_mock):
reply_mock.attribute.return_value = 200
reply_mock.readAll.return_value = QByteArray(json.dumps([self._REMOTE_MATERIAL_WHITE]).encode("cp500"))
job = SendMaterialJob(device_mock)
job._onGetRemoteMaterials(reply_mock)
# Given that the parsing fails we do no expect the device to be called for any follow up.
self.assertEqual(0, device_mock.createFormPart.call_count)
def test__onGetRemoteMaterials_withBadJsonAnswer(self, reply_mock, device_mock):
reply_mock.attribute.return_value = 200
reply_mock.readAll.return_value = QByteArray(b"Six sick hicks nick six slick bricks with picks and sticks.")
job = SendMaterialJob(device_mock)
job._onGetRemoteMaterials(reply_mock)
# Given that the parsing fails we do no expect the device to be called for any follow up.
self.assertEqual(0, device_mock.createFormPart.call_count)
def test__onGetRemoteMaterials_withMissingGuidInRemoteMaterial(self, reply_mock, device_mock):
reply_mock.attribute.return_value = 200
remote_material_without_guid = self._REMOTE_MATERIAL_WHITE.copy()
del remote_material_without_guid["guid"]
reply_mock.readAll.return_value = QByteArray(json.dumps([remote_material_without_guid]).encode("ascii"))
job = SendMaterialJob(device_mock)
job._onGetRemoteMaterials(reply_mock)
# Given that parsing fails we do not expect the device to be called for any follow up.
self.assertEqual(0, device_mock.createFormPart.call_count)
@patch("cura.Settings.CuraContainerRegistry")
@patch("UM.Application")
def test__onGetRemoteMaterials_withInvalidVersionInLocalMaterial(self, application_mock, container_registry_mock,
reply_mock, device_mock):
reply_mock.attribute.return_value = 200
reply_mock.readAll.return_value = QByteArray(json.dumps([self._REMOTE_MATERIAL_WHITE]).encode("ascii"))
localMaterialWhiteWithInvalidVersion = self._LOCAL_MATERIAL_WHITE.copy()
localMaterialWhiteWithInvalidVersion["version"] = "one"
container_registry_mock.findContainersMetadata.return_value = [localMaterialWhiteWithInvalidVersion]
application_mock.getContainerRegistry.return_value = container_registry_mock
with mock.patch.object(Application, "getInstance", new = lambda: application_mock):
job = SendMaterialJob(device_mock)
job._onGetRemoteMaterials(reply_mock)
self.assertEqual(0, device_mock.createFormPart.call_count)
@patch("cura.Settings.CuraContainerRegistry")
@patch("UM.Application")
def test__onGetRemoteMaterials_withNoUpdate(self, application_mock, container_registry_mock, reply_mock,
device_mock):
application_mock.getContainerRegistry.return_value = container_registry_mock
device_mock.createFormPart.return_value = "_xXx_"
container_registry_mock.findContainersMetadata.return_value = [self._LOCAL_MATERIAL_WHITE]
reply_mock.attribute.return_value = 200
reply_mock.readAll.return_value = QByteArray(json.dumps([self._REMOTE_MATERIAL_WHITE]).encode("ascii"))
with mock.patch.object(Application, "getInstance", new = lambda: application_mock):
job = SendMaterialJob(device_mock)
job._onGetRemoteMaterials(reply_mock)
self.assertEqual(0, device_mock.createFormPart.call_count)
self.assertEqual(0, device_mock.postFormWithParts.call_count)
@patch("cura.Settings.CuraContainerRegistry")
@patch("UM.Application")
def test__onGetRemoteMaterials_withUpdatedMaterial(self, application_mock, container_registry_mock, reply_mock,
device_mock):
application_mock.getContainerRegistry.return_value = container_registry_mock
device_mock.createFormPart.return_value = "_xXx_"
localMaterialWhiteWithHigherVersion = self._LOCAL_MATERIAL_WHITE.copy()
localMaterialWhiteWithHigherVersion["version"] = "2"
container_registry_mock.findContainersMetadata.return_value = [localMaterialWhiteWithHigherVersion]
reply_mock.attribute.return_value = 200
reply_mock.readAll.return_value = QByteArray(json.dumps([self._REMOTE_MATERIAL_WHITE]).encode("ascii"))
with mock.patch.object(Application, "getInstance", new = lambda: application_mock):
job = SendMaterialJob(device_mock)
job._onGetRemoteMaterials(reply_mock)
self.assertEqual(1, device_mock.createFormPart.call_count)
self.assertEqual(1, device_mock.postFormWithParts.call_count)
self.assertEquals(
[call.createFormPart("name=\"file\"; filename=\"generic_pla_white.xml.fdm_material\"", "<xml></xml>"),
call.postFormWithParts(target = "materials/", parts = ["_xXx_"], on_finished = job.sendingFinished)],
device_mock.method_calls)
@patch("cura.Settings.CuraContainerRegistry")
@patch("UM.Application")
def test__onGetRemoteMaterials_withNewMaterial(self, application_mock, container_registry_mock, reply_mock,
device_mock):
application_mock.getContainerRegistry.return_value = container_registry_mock
device_mock.createFormPart.return_value = "_xXx_"
container_registry_mock.findContainersMetadata.return_value = [self._LOCAL_MATERIAL_WHITE,
self._LOCAL_MATERIAL_BLACK]
reply_mock.attribute.return_value = 200
reply_mock.readAll.return_value = QByteArray(json.dumps([self._REMOTE_MATERIAL_BLACK]).encode("ascii"))
with mock.patch.object(Application, "getInstance", new = lambda: application_mock):
job = SendMaterialJob(device_mock)
job._onGetRemoteMaterials(reply_mock)
self.assertEqual(1, device_mock.createFormPart.call_count)
self.assertEqual(1, device_mock.postFormWithParts.call_count)
self.assertEquals(
[call.createFormPart("name=\"file\"; filename=\"generic_pla_white.xml.fdm_material\"", "<xml></xml>"),
call.postFormWithParts(target = "materials/", parts = ["_xXx_"], on_finished = job.sendingFinished)],
device_mock.method_calls)

View file

@ -1,40 +0,0 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
import pytest
from UM.Signal import Signal
from cura.CuraApplication import CuraApplication
from cura.Machines.MaterialManager import MaterialManager
# This mock application must extend from Application and not QtApplication otherwise some QObjects are created and
# a segfault is raised.
class FixtureApplication(CuraApplication):
def __init__(self):
super().__init__()
super().initialize()
Signal._signalQueue = self
self.getPreferences().addPreference("cura/favorite_materials", "")
self._material_manager = MaterialManager(self._container_registry, parent = self)
self._material_manager.initialize()
def functionEvent(self, event):
event.call()
def parseCommandLine(self):
pass
def processEvents(self):
pass
@pytest.fixture(autouse=True)
def application():
# Since we need to use it more that once, we create the application the first time and use its instance the second
application = FixtureApplication.getInstance()
if application is None:
application = FixtureApplication()
return application