Fix tests for project notifications.

This commit is contained in:
grossmj 2019-02-23 23:20:11 +07:00
parent 7fe8f7e716
commit 135d56371d
6 changed files with 79 additions and 85 deletions

View File

@ -110,9 +110,9 @@ class Notification:
self.project_emit("node.updated", node.__json__()) self.project_emit("node.updated", node.__json__())
except (aiohttp.web.HTTPNotFound, aiohttp.web.HTTPForbidden): # Project closing except (aiohttp.web.HTTPNotFound, aiohttp.web.HTTPForbidden): # Project closing
return return
# elif action == "ping": elif action == "ping":
# event["compute_id"] = compute_id event["compute_id"] = compute_id
# self.project_emit(action, event) self.project_emit(action, event)
else: else:
self.project_emit(action, event, project_id) self.project_emit(action, event, project_id)

View File

@ -220,22 +220,20 @@ class ProjectHandler:
async def notification(request, response): async def notification(request, response):
controller = Controller.instance() controller = Controller.instance()
project_id = request.match_info["project_id"] project = controller.get_project(request.match_info["project_id"])
response.content_type = "application/json" response.content_type = "application/json"
response.set_status(200) response.set_status(200)
response.enable_chunked_encoding() response.enable_chunked_encoding()
await response.prepare(request) await response.prepare(request)
log.info("New client has connected to the notification stream for project ID '{}' (HTTP long-polling method)".format(project_id)) log.info("New client has connected to the notification stream for project ID '{}' (HTTP long-polling method)".format(project.id))
try: try:
with controller.notification.project_queue(project_id) as queue: with controller.notification.project_queue(project.id) as queue:
while True: while True:
msg = await queue.get_json(5) msg = await queue.get_json(5)
await response.write(("{}\n".format(msg)).encode("utf-8")) await response.write(("{}\n".format(msg)).encode("utf-8"))
finally: finally:
log.info("Client has disconnected from notification for project ID '{}' (HTTP long-polling method)".format(project_id)) log.info("Client has disconnected from notification for project ID '{}' (HTTP long-polling method)".format(project.id))
try:
project = controller.get_project(project_id)
if project.auto_close: if project.auto_close:
# To avoid trouble with client connecting disconnecting we sleep few seconds before checking # To avoid trouble with client connecting disconnecting we sleep few seconds before checking
# if someone else is not connected # if someone else is not connected
@ -243,8 +241,7 @@ class ProjectHandler:
if not controller.notification.project_has_listeners(project.id): if not controller.notification.project_has_listeners(project.id):
log.info("Project '{}' is automatically closing due to no client listening".format(project.id)) log.info("Project '{}' is automatically closing due to no client listening".format(project.id))
await project.close() await project.close()
except aiohttp.web.HTTPNotFound:
pass
@Route.get( @Route.get(
r"/projects/{project_id}/notifications/ws", r"/projects/{project_id}/notifications/ws",
@ -259,36 +256,32 @@ class ProjectHandler:
async def notification_ws(request, response): async def notification_ws(request, response):
controller = Controller.instance() controller = Controller.instance()
project_id = request.match_info["project_id"] project = controller.get_project(request.match_info["project_id"])
ws = aiohttp.web.WebSocketResponse() ws = aiohttp.web.WebSocketResponse()
await ws.prepare(request) await ws.prepare(request)
request.app['websockets'].add(ws) request.app['websockets'].add(ws)
asyncio.ensure_future(process_websocket(ws)) asyncio.ensure_future(process_websocket(ws))
log.info("New client has connected to the notification stream for project ID '{}' (WebSocket method)".format(project_id)) log.info("New client has connected to the notification stream for project ID '{}' (WebSocket method)".format(project.id))
try: try:
with controller.notification.project_queue(project_id) as queue: with controller.notification.project_queue(project.id) as queue:
while True: while True:
notification = await queue.get_json(5) notification = await queue.get_json(5)
if ws.closed: if ws.closed:
break break
await ws.send_str(notification) await ws.send_str(notification)
finally: finally:
log.info("Client has disconnected from notification stream for project ID '{}' (WebSocket method)".format(project_id)) log.info("Client has disconnected from notification stream for project ID '{}' (WebSocket method)".format(project.id))
if not ws.closed: if not ws.closed:
await ws.close() await ws.close()
request.app['websockets'].discard(ws) request.app['websockets'].discard(ws)
try:
project = controller.get_project(project_id)
if project.auto_close: if project.auto_close:
# To avoid trouble with client connecting disconnecting we sleep few seconds before checking # To avoid trouble with client connecting disconnecting we sleep few seconds before checking
# if someone else is not connected # if someone else is not connected
await asyncio.sleep(5) await asyncio.sleep(5)
if not controller.notification.project_has_listeners(project_id): if not controller.notification.project_has_listeners(project.id):
log.info("Project '{}' is automatically closing due to no client listening".format(project.id)) log.info("Project '{}' is automatically closing due to no client listening".format(project.id))
await project.close() await project.close()
except aiohttp.web.HTTPNotFound:
pass
return ws return ws

View File

@ -68,7 +68,7 @@ def test_add_node(async_run, project, compute):
link = Link(project) link = Link(project)
link.create = AsyncioMagicMock() link.create = AsyncioMagicMock()
link._project.controller.notification.project_emit = MagicMock() link._project.emit_notification = MagicMock()
project.dump = AsyncioMagicMock() project.dump = AsyncioMagicMock()
async_run(link.add_node(node1, 0, 4)) async_run(link.add_node(node1, 0, 4))
assert link._nodes == [ assert link._nodes == [
@ -87,7 +87,7 @@ def test_add_node(async_run, project, compute):
} }
] ]
assert project.dump.called assert project.dump.called
assert not link._project.controller.notification.project_emit.called assert not link._project.emit_notification.called
assert not link.create.called assert not link.create.called
@ -97,7 +97,7 @@ def test_add_node(async_run, project, compute):
async_run(link.add_node(node2, 0, 4)) async_run(link.add_node(node2, 0, 4))
assert link.create.called assert link.create.called
link._project.controller.notification.project_emit.assert_called_with("link.created", link.__json__()) link._project.emit_notification.assert_called_with("link.created", link.__json__())
assert link in node2.links assert link in node2.links
@ -112,7 +112,7 @@ def test_add_node_already_connected(async_run, project, compute):
link = Link(project) link = Link(project)
link.create = AsyncioMagicMock() link.create = AsyncioMagicMock()
link._project.controller.notification.project_emit = MagicMock() link._project.emit_notification = MagicMock()
async_run(link.add_node(node1, 0, 4)) async_run(link.add_node(node1, 0, 4))
node2 = Node(project, compute, "node2", node_type="qemu") node2 = Node(project, compute, "node2", node_type="qemu")
node2._ports = [EthernetPort("E0", 0, 0, 4)] node2._ports = [EthernetPort("E0", 0, 0, 4)]
@ -133,7 +133,7 @@ def test_add_node_cloud(async_run, project, compute):
link = Link(project) link = Link(project)
link.create = AsyncioMagicMock() link.create = AsyncioMagicMock()
link._project.controller.notification.project_emit = MagicMock() link._project.emit_notification = MagicMock()
async_run(link.add_node(node1, 0, 4)) async_run(link.add_node(node1, 0, 4))
async_run(link.add_node(node2, 0, 4)) async_run(link.add_node(node2, 0, 4))
@ -150,7 +150,7 @@ def test_add_node_cloud_to_cloud(async_run, project, compute):
link = Link(project) link = Link(project)
link.create = AsyncioMagicMock() link.create = AsyncioMagicMock()
link._project.controller.notification.project_emit = MagicMock() link._project.emit_notification = MagicMock()
async_run(link.add_node(node1, 0, 4)) async_run(link.add_node(node1, 0, 4))
with pytest.raises(aiohttp.web.HTTPConflict): with pytest.raises(aiohttp.web.HTTPConflict):
@ -166,7 +166,7 @@ def test_add_node_same_node(async_run, project, compute):
link = Link(project) link = Link(project)
link.create = AsyncioMagicMock() link.create = AsyncioMagicMock()
link._project.controller.notification.project_emit = MagicMock() link._project.emit_notification = MagicMock()
async_run(link.add_node(node1, 0, 4)) async_run(link.add_node(node1, 0, 4))
with pytest.raises(aiohttp.web.HTTPConflict): with pytest.raises(aiohttp.web.HTTPConflict):
@ -184,7 +184,7 @@ def test_add_node_serial_to_ethernet(async_run, project, compute):
link = Link(project) link = Link(project)
link.create = AsyncioMagicMock() link.create = AsyncioMagicMock()
link._project.controller.notification.project_emit = MagicMock() link._project.emit_notification = MagicMock()
async_run(link.add_node(node1, 0, 4)) async_run(link.add_node(node1, 0, 4))
with pytest.raises(aiohttp.web.HTTPConflict): with pytest.raises(aiohttp.web.HTTPConflict):
@ -295,25 +295,25 @@ def test_default_capture_file_name(project, compute, async_run):
assert link.default_capture_file_name() == "Hello_0-4_to_w0rld_1-3.pcap" assert link.default_capture_file_name() == "Hello_0-4_to_w0rld_1-3.pcap"
def test_start_capture(link, async_run, tmpdir, project, controller): def test_start_capture(link, async_run, tmpdir):
async def fake_reader(): async def fake_reader():
return AsyncioBytesIO() return AsyncioBytesIO()
link.read_pcap_from_source = fake_reader link.read_pcap_from_source = fake_reader
controller._notification = MagicMock() link._project.emit_notification = MagicMock()
async_run(link.start_capture(capture_file_name="test.pcap")) async_run(link.start_capture(capture_file_name="test.pcap"))
assert link._capturing assert link._capturing
assert link._capture_file_name == "test.pcap" assert link._capture_file_name == "test.pcap"
controller._notification.project_emit.assert_called_with("link.updated", link.__json__()) link._project.emit_notification.assert_called_with("link.updated", link.__json__())
def test_stop_capture(link, async_run, tmpdir, project, controller): def test_stop_capture(link, async_run, tmpdir):
link._capturing = True link._capturing = True
controller._notification = MagicMock() link._project.emit_notification = MagicMock()
async_run(link.stop_capture()) async_run(link.stop_capture())
assert link._capturing is False assert link._capturing is False
controller._notification.project_emit.assert_called_with("link.updated", link.__json__()) link._project.emit_notification.assert_called_with("link.updated", link.__json__())
def test_delete(async_run, project, compute): def test_delete(async_run, project, compute):
@ -322,7 +322,7 @@ def test_delete(async_run, project, compute):
link = Link(project) link = Link(project)
link.create = AsyncioMagicMock() link.create = AsyncioMagicMock()
link._project.controller.notification.project_emit = MagicMock() link._project.emit_notification = MagicMock()
project.dump = AsyncioMagicMock() project.dump = AsyncioMagicMock()
async_run(link.add_node(node1, 0, 4)) async_run(link.add_node(node1, 0, 4))
@ -342,7 +342,7 @@ def test_update_filters(async_run, project, compute):
link = Link(project) link = Link(project)
link.create = AsyncioMagicMock() link.create = AsyncioMagicMock()
link._project.controller.notification.project_emit = MagicMock() link._project.emit_notification = MagicMock()
project.dump = AsyncioMagicMock() project.dump = AsyncioMagicMock()
async_run(link.add_node(node1, 0, 4)) async_run(link.add_node(node1, 0, 4))

View File

@ -353,23 +353,23 @@ def test_update_properties(node, compute, project, async_run, controller):
#controller._notification.emit.assert_called_with("node.updated", node_notif) #controller._notification.emit.assert_called_with("node.updated", node_notif)
def test_update_only_controller(node, controller, compute, project, async_run): def test_update_only_controller(node, controller, compute, async_run):
""" """
When updating property used only on controller we don't need to When updating property used only on controller we don't need to
call the compute call the compute
""" """
compute.put = AsyncioMagicMock() compute.put = AsyncioMagicMock()
controller._notification = AsyncioMagicMock() node._project.emit_notification = AsyncioMagicMock()
async_run(node.update(x=42)) async_run(node.update(x=42))
assert not compute.put.called assert not compute.put.called
assert node.x == 42 assert node.x == 42
controller._notification.project_emit.assert_called_with("node.updated", node.__json__()) node._project.emit_notification.assert_called_with("node.updated", node.__json__())
# If nothing change a second notif should not be send # If nothing change a second notif should not be send
controller._notification = AsyncioMagicMock() node._project.emit_notification = AsyncioMagicMock()
async_run(node.update(x=42)) async_run(node.update(x=42))
assert not controller._notification.project_emit.called assert not node._project.emit_notification.called
def test_update_no_changes(node, compute, project, async_run): def test_update_no_changes(node, compute, project, async_run):

View File

@ -45,7 +45,7 @@ def test_emit_to_all(async_run, controller, project):
Send an event to all if we don't have a project id in the event Send an event to all if we don't have a project id in the event
""" """
notif = controller.notification notif = controller.notification
with notif.project_queue(project) as queue: with notif.project_queue(project.id) as queue:
assert len(notif._project_listeners[project.id]) == 1 assert len(notif._project_listeners[project.id]) == 1
async_run(queue.get(0.1)) # ping async_run(queue.get(0.1)) # ping
notif.project_emit('test', {}) notif.project_emit('test', {})
@ -60,7 +60,7 @@ def test_emit_to_project(async_run, controller, project):
Send an event to a project listeners Send an event to a project listeners
""" """
notif = controller.notification notif = controller.notification
with notif.project_queue(project) as queue: with notif.project_queue(project.id) as queue:
assert len(notif._project_listeners[project.id]) == 1 assert len(notif._project_listeners[project.id]) == 1
async_run(queue.get(0.1)) # ping async_run(queue.get(0.1)) # ping
# This event has not listener # This event has not listener
@ -74,20 +74,20 @@ def test_emit_to_project(async_run, controller, project):
def test_dispatch(async_run, controller, project): def test_dispatch(async_run, controller, project):
notif = controller.notification notif = controller.notification
with notif.project_queue(project) as queue: with notif.project_queue(project.id) as queue:
assert len(notif._project_listeners[project.id]) == 1 assert len(notif._project_listeners[project.id]) == 1
async_run(queue.get(0.1)) # ping async_run(queue.get(0.1)) # ping
async_run(notif.dispatch("test", {}, compute_id=1)) async_run(notif.dispatch("test", {}, project_id=project.id, compute_id=1))
msg = async_run(queue.get(5)) msg = async_run(queue.get(5))
assert msg == ('test', {}, {}) assert msg == ('test', {}, {})
def test_dispatch_ping(async_run, controller, project): def test_dispatch_ping(async_run, controller, project):
notif = controller.notification notif = controller.notification
with notif.project_queue(project) as queue: with notif.project_queue(project.id) as queue:
assert len(notif._project_listeners[project.id]) == 1 assert len(notif._project_listeners[project.id]) == 1
async_run(queue.get(0.1)) # ping async_run(queue.get(0.1)) # ping
async_run(notif.dispatch("ping", {}, compute_id=12)) async_run(notif.dispatch("ping", {}, project_id=project.id, compute_id=12))
msg = async_run(queue.get(5)) msg = async_run(queue.get(5))
assert msg == ('ping', {'compute_id': 12}, {}) assert msg == ('ping', {'compute_id': 12}, {})
@ -99,7 +99,7 @@ def test_dispatch_node_updated(async_run, controller, node, project):
""" """
notif = controller.notification notif = controller.notification
with notif.project_queue(project) as queue: with notif.project_queue(project.id) as queue:
assert len(notif._project_listeners[project.id]) == 1 assert len(notif._project_listeners[project.id]) == 1
async_run(queue.get(0.1)) # ping async_run(queue.get(0.1)) # ping
async_run(notif.dispatch("node.updated", { async_run(notif.dispatch("node.updated", {
@ -108,6 +108,7 @@ def test_dispatch_node_updated(async_run, controller, node, project):
"name": "hello", "name": "hello",
"startup_config": "ip 192" "startup_config": "ip 192"
}, },
project_id=project.id,
compute_id=1)) compute_id=1))
assert node.name == "hello" assert node.name == "hello"
action, event, _ = async_run(queue.get(5)) action, event, _ = async_run(queue.get(5))

View File

@ -86,11 +86,11 @@ def test_json(tmpdir):
def test_update(controller, async_run): def test_update(controller, async_run):
project = Project(controller=controller, name="Hello") project = Project(controller=controller, name="Hello")
controller._notification = MagicMock() project.emit_notification = MagicMock()
assert project.name == "Hello" assert project.name == "Hello"
async_run(project.update(name="World")) async_run(project.update(name="World"))
assert project.name == "World" assert project.name == "World"
controller.notification.project_emit.assert_any_call("project.updated", project.__json__()) project.emit_notification.assert_any_call("project.updated", project.__json__())
def test_update_on_compute(controller, async_run): def test_update_on_compute(controller, async_run):
@ -99,7 +99,7 @@ def test_update_on_compute(controller, async_run):
compute.id = "local" compute.id = "local"
project = Project(controller=controller, name="Test") project = Project(controller=controller, name="Test")
project._project_created_on_compute = [compute] project._project_created_on_compute = [compute]
controller._notification = MagicMock() project.emit_notification = MagicMock()
async_run(project.update(variables=variables)) async_run(project.update(variables=variables))
@ -154,7 +154,7 @@ def test_add_node_local(async_run, controller):
compute = MagicMock() compute = MagicMock()
compute.id = "local" compute.id = "local"
project = Project(controller=controller, name="Test") project = Project(controller=controller, name="Test")
controller._notification = MagicMock() project.emit_notification = MagicMock()
response = MagicMock() response = MagicMock()
response.json = {"console": 2048} response.json = {"console": 2048}
@ -174,7 +174,7 @@ def test_add_node_local(async_run, controller):
'name': 'test'}, 'name': 'test'},
timeout=1200) timeout=1200)
assert compute in project._project_created_on_compute assert compute in project._project_created_on_compute
controller.notification.project_emit.assert_any_call("node.created", node.__json__()) project.emit_notification.assert_any_call("node.created", node.__json__())
def test_add_node_non_local(async_run, controller): def test_add_node_non_local(async_run, controller):
@ -184,7 +184,7 @@ def test_add_node_non_local(async_run, controller):
compute = MagicMock() compute = MagicMock()
compute.id = "remote" compute.id = "remote"
project = Project(controller=controller, name="Test") project = Project(controller=controller, name="Test")
controller._notification = MagicMock() project.emit_notification = MagicMock()
response = MagicMock() response = MagicMock()
response.json = {"console": 2048} response.json = {"console": 2048}
@ -202,7 +202,7 @@ def test_add_node_non_local(async_run, controller):
'name': 'test'}, 'name': 'test'},
timeout=1200) timeout=1200)
assert compute in project._project_created_on_compute assert compute in project._project_created_on_compute
controller.notification.project_emit.assert_any_call("node.created", node.__json__()) project.emit_notification.assert_any_call("node.created", node.__json__())
def test_add_node_from_template(async_run, controller): def test_add_node_from_template(async_run, controller):
@ -212,7 +212,7 @@ def test_add_node_from_template(async_run, controller):
compute = MagicMock() compute = MagicMock()
compute.id = "local" compute.id = "local"
project = Project(controller=controller, name="Test") project = Project(controller=controller, name="Test")
controller._notification = MagicMock() project.emit_notification = MagicMock()
template = Template(str(uuid.uuid4()), { template = Template(str(uuid.uuid4()), {
"compute_id": "local", "compute_id": "local",
"name": "Test", "name": "Test",
@ -234,7 +234,7 @@ def test_add_node_from_template(async_run, controller):
}) })
assert compute in project._project_created_on_compute assert compute in project._project_created_on_compute
controller.notification.project_emit.assert_any_call("node.created", node.__json__()) project.emit_notification.assert_any_call("node.created", node.__json__())
def test_delete_node(async_run, controller): def test_delete_node(async_run, controller):
@ -243,7 +243,7 @@ def test_delete_node(async_run, controller):
""" """
compute = MagicMock() compute = MagicMock()
project = Project(controller=controller, name="Test") project = Project(controller=controller, name="Test")
controller._notification = MagicMock() project.emit_notification = MagicMock()
response = MagicMock() response = MagicMock()
response.json = {"console": 2048} response.json = {"console": 2048}
@ -255,7 +255,7 @@ def test_delete_node(async_run, controller):
assert node.id not in project._nodes assert node.id not in project._nodes
compute.delete.assert_any_call('/projects/{}/vpcs/nodes/{}'.format(project.id, node.id)) compute.delete.assert_any_call('/projects/{}/vpcs/nodes/{}'.format(project.id, node.id))
controller.notification.project_emit.assert_any_call("node.deleted", node.__json__()) project.emit_notification.assert_any_call("node.deleted", node.__json__())
def test_delete_node_delete_link(async_run, controller): def test_delete_node_delete_link(async_run, controller):
@ -264,7 +264,7 @@ def test_delete_node_delete_link(async_run, controller):
""" """
compute = MagicMock() compute = MagicMock()
project = Project(controller=controller, name="Test") project = Project(controller=controller, name="Test")
controller._notification = MagicMock() project.emit_notification = MagicMock()
response = MagicMock() response = MagicMock()
response.json = {"console": 2048} response.json = {"console": 2048}
@ -280,8 +280,8 @@ def test_delete_node_delete_link(async_run, controller):
assert link.id not in project._links assert link.id not in project._links
compute.delete.assert_any_call('/projects/{}/vpcs/nodes/{}'.format(project.id, node.id)) compute.delete.assert_any_call('/projects/{}/vpcs/nodes/{}'.format(project.id, node.id))
controller.notification.project_emit.assert_any_call("node.deleted", node.__json__()) project.emit_notification.assert_any_call("node.deleted", node.__json__())
controller.notification.project_emit.assert_any_call("link.deleted", link.__json__()) project.emit_notification.assert_any_call("link.deleted", link.__json__())
def test_get_node(async_run, controller): def test_get_node(async_run, controller):
@ -331,14 +331,14 @@ def test_add_link(async_run, project, controller):
vm1._ports = [EthernetPort("E0", 0, 3, 1)] vm1._ports = [EthernetPort("E0", 0, 3, 1)]
vm2 = async_run(project.add_node(compute, "test2", None, node_type="vpcs", properties={"startup_config": "test.cfg"})) vm2 = async_run(project.add_node(compute, "test2", None, node_type="vpcs", properties={"startup_config": "test.cfg"}))
vm2._ports = [EthernetPort("E0", 0, 4, 2)] vm2._ports = [EthernetPort("E0", 0, 4, 2)]
controller._notification = MagicMock() project.emit_notification = MagicMock()
link = async_run(project.add_link()) link = async_run(project.add_link())
async_run(link.add_node(vm1, 3, 1)) async_run(link.add_node(vm1, 3, 1))
with asyncio_patch("gns3server.controller.udp_link.UDPLink.create") as mock_udp_create: with asyncio_patch("gns3server.controller.udp_link.UDPLink.create") as mock_udp_create:
async_run(link.add_node(vm2, 4, 2)) async_run(link.add_node(vm2, 4, 2))
assert mock_udp_create.called assert mock_udp_create.called
assert len(link._nodes) == 2 assert len(link._nodes) == 2
controller.notification.project_emit.assert_any_call("link.created", link.__json__()) project.emit_notification.assert_any_call("link.created", link.__json__())
def test_list_links(async_run, project): def test_list_links(async_run, project):
@ -379,18 +379,18 @@ def test_delete_link(async_run, project, controller):
assert len(project._links) == 0 assert len(project._links) == 0
link = async_run(project.add_link()) link = async_run(project.add_link())
assert len(project._links) == 1 assert len(project._links) == 1
controller._notification = MagicMock() project.emit_notification = MagicMock()
async_run(project.delete_link(link.id)) async_run(project.delete_link(link.id))
controller.notification.project_emit.assert_any_call("link.deleted", link.__json__()) project.emit_notification.assert_any_call("link.deleted", link.__json__())
assert len(project._links) == 0 assert len(project._links) == 0
def test_add_drawing(async_run, project, controller): def test_add_drawing(async_run, project, controller):
controller.notification.project_emit = MagicMock() project.emit_notification = MagicMock()
drawing = async_run(project.add_drawing(None, svg="<svg></svg>")) drawing = async_run(project.add_drawing(None, svg="<svg></svg>"))
assert len(project._drawings) == 1 assert len(project._drawings) == 1
controller.notification.project_emit.assert_any_call("drawing.created", drawing.__json__()) project.emit_notification.assert_any_call("drawing.created", drawing.__json__())
def test_get_drawing(async_run, project): def test_get_drawing(async_run, project):
@ -413,9 +413,9 @@ def test_delete_drawing(async_run, project, controller):
assert len(project._drawings) == 0 assert len(project._drawings) == 0
drawing = async_run(project.add_drawing()) drawing = async_run(project.add_drawing())
assert len(project._drawings) == 1 assert len(project._drawings) == 1
controller._notification = MagicMock() project.emit_notification = MagicMock()
async_run(project.delete_drawing(drawing.id)) async_run(project.delete_drawing(drawing.id))
controller.notification.project_emit.assert_any_call("drawing.deleted", drawing.__json__()) project.emit_notification.assert_any_call("drawing.deleted", drawing.__json__())
assert len(project._drawings) == 0 assert len(project._drawings) == 0
@ -478,10 +478,10 @@ def test_open_close(async_run, controller):
async_run(project.open()) async_run(project.open())
assert not project.start_all.called assert not project.start_all.called
assert project.status == "opened" assert project.status == "opened"
controller._notification = MagicMock() project.emit_notification = MagicMock()
async_run(project.close()) async_run(project.close())
assert project.status == "closed" assert project.status == "closed"
controller.notification.project_emit.assert_any_call("project.closed", project.__json__()) project.emit_notification.assert_any_call("project.closed", project.__json__())
def test_open_auto_start(async_run, controller): def test_open_auto_start(async_run, controller):