diff --git a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py index f06bbb305e..961f8d696d 100644 --- a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py +++ b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py @@ -22,7 +22,6 @@ from .Utils import findChanges # # API spec is available on https://api.ultimaker.com/docs/connect/spec/. # - class CloudOutputDeviceManager: META_CLUSTER_ID = "um_cloud_cluster_id" @@ -32,9 +31,7 @@ class CloudOutputDeviceManager: # The translation catalog for this device. I18N_CATALOG = i18nCatalog("cura") - def __init__(self): - super().__init__() - + def __init__(self) -> None: # Persistent dict containing the remote clusters for the authenticated user. self._remote_clusters = {} # type: Dict[str, CloudOutputDevice] @@ -86,6 +83,7 @@ class CloudOutputDeviceManager: for removed_cluster in removed_devices: if removed_cluster.isConnected(): removed_cluster.disconnect() + removed_cluster.close() self._output_device_manager.removeOutputDevice(removed_cluster.key) del self._remote_clusters[removed_cluster.key] @@ -124,20 +122,17 @@ class CloudOutputDeviceManager: return device = next((c for c in self._remote_clusters.values() if c.matchesNetworkKey(local_network_key)), None) - if not device: - return - - active_machine.setMetaDataEntry(self.META_CLUSTER_ID, device.key) - return device.connect() + if device: + active_machine.setMetaDataEntry(self.META_CLUSTER_ID, device.key) + device.connect() ## Handles an API error received from the cloud. # \param errors: The errors received def _onApiError(self, errors: List[CloudErrorObject]) -> None: message = ". ".join(e.title for e in errors) # TODO: translate errors - message = Message( + Message( text = message, title = self.I18N_CATALOG.i18nc("@info:title", "Error"), lifetime = 10, dismissable = True - ) - message.show() + ).show() diff --git a/plugins/UM3NetworkPrinting/tests/Cloud/Fixtures/clusters.json b/plugins/UM3NetworkPrinting/tests/Cloud/Fixtures/clusters.json index 79a4c30113..5200e3b971 100644 --- a/plugins/UM3NetworkPrinting/tests/Cloud/Fixtures/clusters.json +++ b/plugins/UM3NetworkPrinting/tests/Cloud/Fixtures/clusters.json @@ -9,7 +9,7 @@ }, { "cluster_id": "NWKV6vJP_LdYsXgXqAcaNCR0YcLJwar1ugh0ikEZsZs8", "host_guid": "e0ace90a-91ee-1257-4403-e8050a44c9b7", - "host_name": "ultimakersystem-ccbdd30044ec", + "host_name": "ultimakersystem-30044ecccbdd", "host_version": "5.1.2.20180807", "is_online": true, "status": "active" diff --git a/plugins/UM3NetworkPrinting/tests/Cloud/TestCloudOutputDeviceManager.py b/plugins/UM3NetworkPrinting/tests/Cloud/TestCloudOutputDeviceManager.py index a043288e59..80ce54aeee 100644 --- a/plugins/UM3NetworkPrinting/tests/Cloud/TestCloudOutputDeviceManager.py +++ b/plugins/UM3NetworkPrinting/tests/Cloud/TestCloudOutputDeviceManager.py @@ -30,13 +30,18 @@ class TestCloudOutputDeviceManager(TestCase): # let the network send replies self.network.flushReplies() # get the created devices - devices = self.app.getOutputDeviceManager().getOutputDevices() + device_manager = self.app.getOutputDeviceManager() + devices = device_manager.getOutputDevices() # get the server data - clusters = self.clusters_response["data"] + clusters = self.clusters_response.get("data", []) self.assertEqual([CloudOutputDevice] * len(clusters), [type(d) for d in devices]) self.assertEqual({cluster["cluster_id"] for cluster in clusters}, {device.key for device in devices}) self.assertEqual({cluster["host_name"] for cluster in clusters}, {device.host_name for device in devices}) + for device in clusters: + device_manager.getOutputDevice(device["cluster_id"]).close() + device_manager.removeOutputDevice(device["cluster_id"]) + ## Runs the initial request to retrieve the clusters. def _loadData(self, network_mock): network_mock.return_value = self.network @@ -64,3 +69,39 @@ class TestCloudOutputDeviceManager(TestCase): self.network.prepareGetClusters(self.clusters_response) self.manager._update_timer.timeout.emit() + + @patch("cura.CuraApplication.CuraApplication.getGlobalContainerStack") + def test_device_connects_by_cluster_id(self, global_container_stack_mock, network_mock): + active_machine_mock = global_container_stack_mock.return_value + cluster1, cluster2 = self.clusters_response["data"] + cluster_id = cluster1["cluster_id"] + active_machine_mock.getMetaDataEntry.side_effect = {"um_cloud_cluster_id": cluster_id}.get + + self._loadData(network_mock) + self.network.flushReplies() + + self.assertTrue(self.app.getOutputDeviceManager().getOutputDevice(cluster1["cluster_id"]).isConnected()) + self.assertFalse(self.app.getOutputDeviceManager().getOutputDevice(cluster2["cluster_id"]).isConnected()) + + @patch("cura.CuraApplication.CuraApplication.getGlobalContainerStack") + def test_device_connects_by_network_key(self, global_container_stack_mock, network_mock): + active_machine_mock = global_container_stack_mock.return_value + + cluster1, cluster2 = self.clusters_response["data"] + network_key = cluster2["host_name"] + ".ultimaker.local" + active_machine_mock.getMetaDataEntry.side_effect = {"um_network_key": network_key}.get + + self._loadData(network_mock) + self.network.flushReplies() + + self.assertFalse(self.app.getOutputDeviceManager().getOutputDevice(cluster1["cluster_id"]).isConnected()) + self.assertTrue(self.app.getOutputDeviceManager().getOutputDevice(cluster2["cluster_id"]).isConnected()) + + active_machine_mock.setMetaDataEntry.assert_called_once_with("um_cloud_cluster_id", cluster2["cluster_id"]) + + @patch("UM.Message.Message.show") + def test_api_error(self, message_mock, network_mock): + self.clusters_response = {"errors": [{"id": "notFound"}]} + self.network.prepareGetClusters(self.clusters_response) + self._loadData(network_mock) + message_mock.assert_called_once_with()