From 6e7bfacd08a0ce4b87d12963bc53d67ce6326467 Mon Sep 17 00:00:00 2001 From: Lukas Juhrich Date: Thu, 29 Jun 2023 15:57:31 +0200 Subject: [PATCH 01/14] [tests] Test `host_delete` Refs #641 --- tests/factories/property.py | 21 ++++++++++----- tests/frontend/test_host.py | 48 +++++++++++++++++++++++++++++++++ web/blueprints/host/__init__.py | 2 +- 3 files changed, 64 insertions(+), 7 deletions(-) create mode 100644 tests/frontend/test_host.py diff --git a/tests/factories/property.py b/tests/factories/property.py index f4d606aab..8138d0f4e 100644 --- a/tests/factories/property.py +++ b/tests/factories/property.py @@ -59,12 +59,21 @@ def property_grants(self): class AdminPropertyGroupFactory(PropertyGroupFactory): name = factory.Sequence(partial(_maybe_append_seq, prefix="Admin-Gruppe")) - granted = frozenset(( - 'user_show', 'user_change', 'user_mac_change', - 'infrastructure_show', 'infrastructure_change', - 'facilities_show', 'facilities_change', - 'groups_show', 'groups_change_membership', 'groups_change', - )) + granted = frozenset( + ( + "user_show", + "user_change", + "user_mac_change", + "hosts_change", + "infrastructure_show", + "infrastructure_change", + "facilities_show", + "facilities_change", + "groups_show", + "groups_change_membership", + "groups_change", + ) + ) permission_level = 10 diff --git a/tests/frontend/test_host.py b/tests/frontend/test_host.py new file mode 100644 index 000000000..27d8beac8 --- /dev/null +++ b/tests/frontend/test_host.py @@ -0,0 +1,48 @@ +# Copyright (c) 2015 The Pycroft Authors. See the AUTHORS file. +# This file is part of the Pycroft project and licensed under the terms of +# the Apache License, Version 2.0. See the LICENSE file for details. + +import pytest +from flask import url_for + +from pycroft.model.host import Host +from pycroft.model.user import User +from tests import factories as f + +from .assertions import TestClient + + +@pytest.fixture(scope="module") +def client(module_test_client: TestClient) -> TestClient: + return module_test_client + + +@pytest.fixture(scope="module") +def owner(module_session) -> User: + return f.UserFactory() + + +@pytest.fixture(scope="module") +def host(module_session, owner) -> Host: + return f.HostFactory(owner=owner) + + +@pytest.mark.usefixtures("admin_logged_in") +class TestHostDelete: + def test_delete_nonexistent_host(self, client): + client.assert_url_response_code( + url_for("host.host_delete", host_id=999), code=404 + ) + + def test_host_delete_successful(self, session, client, host, owner): + with client.flashes_message("Host.*gelöscht", category="success"): + client.assert_url_redirects( + url_for("host.host_delete", host_id=host.id), + method="POST", + ) + session.refresh(owner) + assert owner.hosts == [] + + def test_host_get_returns_form(self, client, host): + with client.renders_template("generic_form.html"): + client.assert_url_ok(url_for("host.host_delete", host_id=host.id)) diff --git a/web/blueprints/host/__init__.py b/web/blueprints/host/__init__.py index fcf48e0b6..897e5029f 100644 --- a/web/blueprints/host/__init__.py +++ b/web/blueprints/host/__init__.py @@ -55,7 +55,7 @@ def default_response(): with handle_errors(session.session): lib_host.host_delete(host, current_user) session.session.commit() - except PycroftException: + except PycroftException: # pragma: no cover return default_response() flash("Host erfolgreich gelöscht.", 'success') From 9821ffabc7766add717b3ff2e8efe5873e95bbf2 Mon Sep 17 00:00:00 2001 From: Lukas Juhrich Date: Thu, 29 Jun 2023 16:23:02 +0200 Subject: [PATCH 02/14] [tests] test `host_edit` Refs #641 --- tests/frontend/test_host.py | 47 +++++++++++++++++++++++++++++++++ web/blueprints/host/__init__.py | 2 +- 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/tests/frontend/test_host.py b/tests/frontend/test_host.py index 27d8beac8..5455a8feb 100644 --- a/tests/frontend/test_host.py +++ b/tests/frontend/test_host.py @@ -46,3 +46,50 @@ def test_host_delete_successful(self, session, client, host, owner): def test_host_get_returns_form(self, client, host): with client.renders_template("generic_form.html"): client.assert_url_ok(url_for("host.host_delete", host_id=host.id)) + + +@pytest.mark.usefixtures("admin_logged_in") +class TestHostEdit: + def test_edit_nonexistent_host(self, client): + client.assert_url_response_code( + url_for("host.host_edit", host_id=999), code=404 + ) + + def test_edit_host_get(self, client, host): + with client.renders_template("generic_form.html"): + client.assert_url_ok(url_for("host.host_edit", host_id=host.id)) + + def test_post_without_data(self, client, host): + """works because the room data is automatically derived from the host""" + # HTTP 200 OK although form invalid + client.assert_url_ok( + url_for("host.host_edit", host_id=host.id), + method="POST", + ) + + def test_post_with_data(self, client, host): + with client.flashes_message("Host.*bearbeitet", category="success"): + client.assert_url_redirects( + url_for("host.host_edit", host_id=host.id), + method="POST", + data={ + "owner": host.owner.id, + "name": f"new-{host.name}", + "building": host.room.building.id, + "level": host.room.level, + "room_number": host.room.number, + }, + ) + + def test_post_with_invalid_data(self, client, host): + client.assert_url_ok( + url_for("host.host_edit", host_id=host.id), + method="POST", + data={ + "owner": host.owner.id, + "name": f"new-{host.name}", + "building": host.room.building.id, + "level": host.room.level, + "room_number": 999, + }, + ) diff --git a/web/blueprints/host/__init__.py b/web/blueprints/host/__init__.py index 897e5029f..d82bc42aa 100644 --- a/web/blueprints/host/__init__.py +++ b/web/blueprints/host/__init__.py @@ -105,7 +105,7 @@ def default_response(): processor=current_user ) session.session.commit() - except PycroftException: + except PycroftException: # pragma: no cover return default_response() flash("Host erfolgreich bearbeitet.", 'success') From 7632d662bc6e8cdab1911e98403ee502d360178d Mon Sep 17 00:00:00 2001 From: Lukas Juhrich Date: Thu, 29 Jun 2023 16:38:34 +0200 Subject: [PATCH 03/14] [tests] test `host_create` and add success flash message Refs #641 --- tests/frontend/test_host.py | 45 +++++++++++++++++++++++++++++++++ web/blueprints/host/__init__.py | 12 +++++---- 2 files changed, 52 insertions(+), 5 deletions(-) diff --git a/tests/frontend/test_host.py b/tests/frontend/test_host.py index 5455a8feb..321298acc 100644 --- a/tests/frontend/test_host.py +++ b/tests/frontend/test_host.py @@ -93,3 +93,48 @@ def test_post_with_invalid_data(self, client, host): "room_number": 999, }, ) + + +@pytest.mark.usefixtures("admin_logged_in") +class TestHostCreate: + def test_create_host_nonexistent_owner(self, client): + client.assert_url_response_code( + url_for("host.host_create", user_id=999), code=404 + ) + + def test_create_host_get(self, client, owner): + with client.renders_template("generic_form.html"): + client.assert_url_ok(url_for("host.host_create", user_id=owner.id)) + + def test_create_host_post(self, session, client, owner, host): + with client.flashes_message("Host.*erstellt", category="success"): + client.assert_url_redirects( + url_for("host.host_create", user_id=owner.id), + method="POST", + data={ + "name": "test-host", + "building": owner.room.building.id, + "level": owner.room.level, + "room_number": owner.room.number, + }, + ) + session.refresh(owner) + # assert len(owner.hosts) == 1 + # assert owner.hosts[0].name == "test-host" + new_hosts = set(owner.hosts) - {host} + assert len(new_hosts) == 1 + assert list(new_hosts)[0].name == "test-host" + + def test_create_host_post_invalid_data(self, session, client, owner): + client.assert_url_ok( + url_for("host.host_create", user_id=owner.id), + method="POST", + data={ + "name": "test-host", + "building": owner.room.building.id, + "level": owner.room.level, + "room_number": 999, + }, + ) + session.refresh(owner) + assert len(owner.hosts) == 1 diff --git a/web/blueprints/host/__init__.py b/web/blueprints/host/__init__.py index d82bc42aa..a54746a59 100644 --- a/web/blueprints/host/__init__.py +++ b/web/blueprints/host/__init__.py @@ -157,13 +157,15 @@ def default_response(): owner, room, form.name.data, processor=current_user ) session.session.commit() - except PycroftException: + except PycroftException: # pragma: no cover return default_response() - return redirect(url_for( - '.interface_create', - user_id=host.owner_id, host_id=host.id, _anchor='hosts' - )) + flash("Host erfolgreich erstellt.", "success") + return redirect( + url_for( + ".interface_create", user_id=host.owner_id, host_id=host.id, _anchor="hosts" + ) + ) @bp.route("//interfaces") From 79e2d15692d3181fdc9a41e4392805849f1fc1a4 Mon Sep 17 00:00:00 2001 From: Lukas Juhrich Date: Thu, 29 Jun 2023 17:01:54 +0200 Subject: [PATCH 04/14] [tests] test `interface_delete` Refs #641 --- tests/frontend/test_interface.py | 52 ++++++++++++++++++++++++++++++++ web/blueprints/host/__init__.py | 2 +- 2 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 tests/frontend/test_interface.py diff --git a/tests/frontend/test_interface.py b/tests/frontend/test_interface.py new file mode 100644 index 000000000..9ecbcfa53 --- /dev/null +++ b/tests/frontend/test_interface.py @@ -0,0 +1,52 @@ +# Copyright (c) 2015 The Pycroft Authors. See the AUTHORS file. +# This file is part of the Pycroft project and licensed under the terms of +# the Apache License, Version 2.0. See the LICENSE file for details. + +import pytest +from flask import url_for + +from pycroft.model.host import Host, Interface +from tests import factories as f + +from .assertions import TestClient + + +@pytest.fixture(scope="module") +def client(module_test_client: TestClient) -> TestClient: + return module_test_client + + +@pytest.fixture(scope="module", autouse=True) +def host(module_session) -> Host: + return f.HostFactory(interface=None) + + +@pytest.fixture(scope="module", autouse=True) +def interface(module_session, host) -> Interface: + return f.InterfaceFactory(host=host) + + +pytestmark = pytest.mark.usefixtures("admin_logged_in") + + +@pytest.mark.usefixtures("session") +class TestInterfaceDelete: + def test_delete_nonexistent_interface(self, client): + client.assert_url_response_code( + url_for("host.interface_delete", interface_id=999), code=404 + ) + + def test_delete_interface_get(self, client, interface): + with client.renders_template("generic_form.html"): + client.assert_url_ok( + url_for("host.interface_delete", interface_id=interface.id) + ) + + def test_delete_interface_post(self, session, client, interface): + with client.flashes_message("Interface.*gelöscht", category="success"): + client.assert_url_redirects( + url_for("host.interface_delete", interface_id=interface.id), + method="POST", + ) + session.refresh(host) + assert interface not in host.interfaces diff --git a/web/blueprints/host/__init__.py b/web/blueprints/host/__init__.py index a54746a59..b8cdcc2b9 100644 --- a/web/blueprints/host/__init__.py +++ b/web/blueprints/host/__init__.py @@ -242,7 +242,7 @@ def default_response(): with handle_errors(session.session): lib_host.interface_delete(interface, current_user) session.session.commit() - except PycroftException: + except PycroftException: # pragma: no cover return default_response() flash("Interface erfolgreich gelöscht.", 'success') From 55357356151204718be7c5d0c88a5809185abda7 Mon Sep 17 00:00:00 2001 From: Lukas Juhrich Date: Thu, 29 Jun 2023 17:18:24 +0200 Subject: [PATCH 05/14] [tests] test `interface_edit` Refs #641 --- tests/frontend/test_interface.py | 35 +++++++++++++++++++++++++++++++- web/blueprints/host/__init__.py | 2 +- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/tests/frontend/test_interface.py b/tests/frontend/test_interface.py index 9ecbcfa53..6bbbf7905 100644 --- a/tests/frontend/test_interface.py +++ b/tests/frontend/test_interface.py @@ -42,7 +42,7 @@ def test_delete_interface_get(self, client, interface): url_for("host.interface_delete", interface_id=interface.id) ) - def test_delete_interface_post(self, session, client, interface): + def test_delete_interface_post(self, session, client, interface, host): with client.flashes_message("Interface.*gelöscht", category="success"): client.assert_url_redirects( url_for("host.interface_delete", interface_id=interface.id), @@ -50,3 +50,36 @@ def test_delete_interface_post(self, session, client, interface): ) session.refresh(host) assert interface not in host.interfaces + + +@pytest.mark.usefixtures("session") +class TestInterfaceEdit: + def test_edit_nonexistent_interface(self, client): + client.assert_url_response_code( + url_for("host.interface_edit", interface_id=999), code=404 + ) + + def test_edit_interface_get(self, client, interface): + with client.renders_template("generic_form.html"): + client.assert_url_ok( + url_for("host.interface_edit", interface_id=interface.id) + ) + + def test_edit_interface_post_invalid_data(self, client, interface): + with client.renders_template("generic_form.html"): + client.assert_url_ok( + url_for("host.interface_edit", interface_id=interface.id), + data={"mac": "invalid"}, + method="POST", + ) + + def test_edit_interface_success(self, session, client, interface): + with client.flashes_message("Interface.*bearbeitet", category="success"): + client.assert_url_redirects( + url_for("host.interface_edit", interface_id=interface.id), + method="POST", + data={"mac": "00:11:22:33:44:55", "name": "new name"}, + ) + session.refresh(interface) + assert interface.mac == "00:11:22:33:44:55" + assert interface.name == "new name" diff --git a/web/blueprints/host/__init__.py b/web/blueprints/host/__init__.py index b8cdcc2b9..9118c0770 100644 --- a/web/blueprints/host/__init__.py +++ b/web/blueprints/host/__init__.py @@ -292,7 +292,7 @@ def default_response(): processor=current_user ) session.session.commit() - except PycroftException: + except PycroftException: # pragma: no cover return default_response() flash("Interface erfolgreich bearbeitet.", 'success') From 0a8c91e7feff2df498c33f6d46313deba74cd325 Mon Sep 17 00:00:00 2001 From: Lukas Juhrich Date: Thu, 29 Jun 2023 17:26:23 +0200 Subject: [PATCH 06/14] [web] Don't ignore validation in `interface_edit` --- web/blueprints/host/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/blueprints/host/__init__.py b/web/blueprints/host/__init__.py index 9118c0770..a0e98e704 100644 --- a/web/blueprints/host/__init__.py +++ b/web/blueprints/host/__init__.py @@ -280,7 +280,7 @@ def default_response(): if not form.is_submitted(): form.ips.process_data(ip for ip in current_ips) return default_response() - if not form.validate: + if not form.validate(): return default_response() ips = {IPv4Address(ip) for ip in form.ips.data} From 039063f72d3f3cf5ac785706fa227b64d94c196c Mon Sep 17 00:00:00 2001 From: Lukas Juhrich Date: Thu, 29 Jun 2023 17:39:37 +0200 Subject: [PATCH 07/14] [tests] Test `interface_create` Refs #641 --- tests/frontend/test_interface.py | 28 ++++++++++++++++++++++++++++ web/blueprints/host/__init__.py | 2 +- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/tests/frontend/test_interface.py b/tests/frontend/test_interface.py index 6bbbf7905..aeffc0c06 100644 --- a/tests/frontend/test_interface.py +++ b/tests/frontend/test_interface.py @@ -83,3 +83,31 @@ def test_edit_interface_success(self, session, client, interface): session.refresh(interface) assert interface.mac == "00:11:22:33:44:55" assert interface.name == "new name" + + +@pytest.mark.usefixtures("session") +class TestInterfaceCreate: + def test_create_interface_nonexistent_host(self, client, host): + client.assert_url_response_code( + url_for("host.interface_create", host_id=999), code=404 + ) + + def test_create_interface_get(self, client, host): + with client.renders_template("generic_form.html"): + client.assert_url_ok(url_for("host.interface_create", host_id=host.id)) + + def test_create_interface_post_invalid_data(self, client, host): + with client.renders_template("generic_form.html"): + client.assert_url_ok( + url_for("host.interface_create", host_id=host.id), + method="POST", + data={"mac": "invalid"}, + ) + + def test_create_interface_success(self, client, host): + with client.flashes_message("Interface.*erstellt", category="success"): + client.assert_url_redirects( + url_for("host.interface_create", host_id=host.id), + method="POST", + data={"mac": "00:11:22:33:44:55", "name": "new name"}, + ) diff --git a/web/blueprints/host/__init__.py b/web/blueprints/host/__init__.py index a0e98e704..0398702a7 100644 --- a/web/blueprints/host/__init__.py +++ b/web/blueprints/host/__init__.py @@ -338,7 +338,7 @@ def default_response(): current_user ) session.session.commit() - except PycroftException: + except PycroftException: # pragma: no cover return default_response() flash("Interface erfolgreich erstellt.", 'success') From ca657a6750fe2a635c83e0fd35579719b21a2b36 Mon Sep 17 00:00:00 2001 From: Lukas Juhrich Date: Thu, 29 Jun 2023 19:32:19 +0200 Subject: [PATCH 08/14] [tests] test `interfaces_json` Refs #641 --- tests/frontend/test_interface.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/frontend/test_interface.py b/tests/frontend/test_interface.py index aeffc0c06..971b0533c 100644 --- a/tests/frontend/test_interface.py +++ b/tests/frontend/test_interface.py @@ -29,6 +29,26 @@ def interface(module_session, host) -> Interface: pytestmark = pytest.mark.usefixtures("admin_logged_in") +class TestInterfacesJson: + def test_interfaces_nonexistent_host(self, client): + client.assert_url_response_code( + url_for("host.host_interfaces_json", host_id=999), code=404 + ) + + def test_interfaces_json(self, client, interface): + resp = client.assert_url_ok( + url_for("host.host_interfaces_json", host_id=interface.host.id) + ) + + assert "items" in resp.json + items = resp.json["items"] + assert len(items) == 1 + [item] = items + assert item["id"] == interface.id + assert len(item["actions"]) == 2 + assert item["ips"] != "" + + @pytest.mark.usefixtures("session") class TestInterfaceDelete: def test_delete_nonexistent_interface(self, client): From f3a5225b21008b761a47ccce9703d58af3aeb6fb Mon Sep 17 00:00:00 2001 From: Lukas Juhrich Date: Thu, 29 Jun 2023 19:41:21 +0200 Subject: [PATCH 09/14] [ci] Disable ruff rule for `pyi` stubs --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index 7338d0b3b..c47d602d1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -119,3 +119,4 @@ unfixable = [ "__init__.py" = ["E402", "F401"] "pycroft/model/_all.py" = ["F403"] "helpers/interactive.py" = ["F403"] +"**/*.pyi" = ["F811"] From fefa257eed033d0cfc7a1436cc6c4c779171b6d9 Mon Sep 17 00:00:00 2001 From: Lukas Juhrich Date: Thu, 29 Jun 2023 19:45:50 +0200 Subject: [PATCH 10/14] [tests] test `interface_table` #641 --- tests/frontend/test_interface.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/frontend/test_interface.py b/tests/frontend/test_interface.py index 971b0533c..ecb94b0ac 100644 --- a/tests/frontend/test_interface.py +++ b/tests/frontend/test_interface.py @@ -49,6 +49,11 @@ def test_interfaces_json(self, client, interface): assert item["ips"] != "" +def test_interface_table(client, interface): + with client.renders_template("host/interface_table.html"): + client.assert_url_ok(url_for("host.interface_table", host_id=interface.host_id)) + + @pytest.mark.usefixtures("session") class TestInterfaceDelete: def test_delete_nonexistent_interface(self, client): From 50f4f34a13c590c3ecb459d179af1309561ecf73 Mon Sep 17 00:00:00 2001 From: Lukas Juhrich Date: Thu, 29 Jun 2023 20:11:19 +0200 Subject: [PATCH 11/14] [tests] test `user_hosts_json` #641 --- tests/frontend/test_interface.py | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/tests/frontend/test_interface.py b/tests/frontend/test_interface.py index ecb94b0ac..45e84e02c 100644 --- a/tests/frontend/test_interface.py +++ b/tests/frontend/test_interface.py @@ -18,7 +18,7 @@ def client(module_test_client: TestClient) -> TestClient: @pytest.fixture(scope="module", autouse=True) def host(module_session) -> Host: - return f.HostFactory(interface=None) + return f.HostFactory(interface=None, room__patched_with_subnet=True) @pytest.fixture(scope="module", autouse=True) @@ -54,6 +54,34 @@ def test_interface_table(client, interface): client.assert_url_ok(url_for("host.interface_table", host_id=interface.host_id)) +def test_user_hosts(client, host): + resp = client.assert_url_ok(url_for("host.user_hosts_json", user_id=host.owner.id)) + + assert "items" in resp.json + items = resp.json["items"] + assert len(items) == 1 + [item] = items + assert item["switch"] + assert item["port"] + assert item["id"] == host.id + assert len(item["actions"]) == 2 + + +@pytest.fixture() +def host_without_room(session): + return f.HostFactory(room=None) + + +def test_user_host_without_room(client, host_without_room): + resp = client.assert_url_ok( + url_for("host.user_hosts_json", user_id=host_without_room.owner.id) + ) + assert len(resp.json["items"]) == 1 + [it] = resp.json["items"] + assert it["switch"] is None + assert it["port"] is None + + @pytest.mark.usefixtures("session") class TestInterfaceDelete: def test_delete_nonexistent_interface(self, client): From 69d8103018651c9711496b82f3e99e9a8377561b Mon Sep 17 00:00:00 2001 From: Lukas Juhrich Date: Thu, 29 Jun 2023 20:11:36 +0200 Subject: [PATCH 12/14] [web] handle unnamed switches in host table This fixes a bug uncovered by #641. --- web/blueprints/host/__init__.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/web/blueprints/host/__init__.py b/web/blueprints/host/__init__.py index 0398702a7..404bb7bb5 100644 --- a/web/blueprints/host/__init__.py +++ b/web/blueprints/host/__init__.py @@ -358,7 +358,9 @@ def user_hosts_json(user_id): if host.room: patch_ports = host.room.connected_patch_ports switches = ', '.join( - p.switch_port.switch.host.name for p in patch_ports) + p.switch_port.switch.host.name or "" + for p in patch_ports + ) ports = ', '.join(p.switch_port.name for p in patch_ports) else: switches = None From fd9f934f0c7ff366dbc5a8d98c758dc066bfdc09 Mon Sep 17 00:00:00 2001 From: Lukas Juhrich Date: Thu, 29 Jun 2023 20:17:28 +0200 Subject: [PATCH 13/14] Move `test_user_hosts` to proper file --- tests/frontend/test_host.py | 30 +++++++++++++++++++++++++++++- tests/frontend/test_interface.py | 28 ---------------------------- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/tests/frontend/test_host.py b/tests/frontend/test_host.py index 321298acc..d28d45892 100644 --- a/tests/frontend/test_host.py +++ b/tests/frontend/test_host.py @@ -24,7 +24,7 @@ def owner(module_session) -> User: @pytest.fixture(scope="module") def host(module_session, owner) -> Host: - return f.HostFactory(owner=owner) + return f.HostFactory(owner=owner, room__patched_with_subnet=True) @pytest.mark.usefixtures("admin_logged_in") @@ -138,3 +138,31 @@ def test_create_host_post_invalid_data(self, session, client, owner): ) session.refresh(owner) assert len(owner.hosts) == 1 + + +def test_user_hosts(client, host): + resp = client.assert_url_ok(url_for("host.user_hosts_json", user_id=host.owner.id)) + + assert "items" in resp.json + items = resp.json["items"] + assert len(items) == 1 + [item] = items + assert item["switch"] + assert item["port"] + assert item["id"] == host.id + assert len(item["actions"]) == 2 + + +@pytest.fixture() +def host_without_room(session): + return f.HostFactory(room=None) + + +def test_user_host_without_room(client, host_without_room): + resp = client.assert_url_ok( + url_for("host.user_hosts_json", user_id=host_without_room.owner.id) + ) + assert len(resp.json["items"]) == 1 + [it] = resp.json["items"] + assert it["switch"] is None + assert it["port"] is None diff --git a/tests/frontend/test_interface.py b/tests/frontend/test_interface.py index 45e84e02c..4e48cbe26 100644 --- a/tests/frontend/test_interface.py +++ b/tests/frontend/test_interface.py @@ -54,34 +54,6 @@ def test_interface_table(client, interface): client.assert_url_ok(url_for("host.interface_table", host_id=interface.host_id)) -def test_user_hosts(client, host): - resp = client.assert_url_ok(url_for("host.user_hosts_json", user_id=host.owner.id)) - - assert "items" in resp.json - items = resp.json["items"] - assert len(items) == 1 - [item] = items - assert item["switch"] - assert item["port"] - assert item["id"] == host.id - assert len(item["actions"]) == 2 - - -@pytest.fixture() -def host_without_room(session): - return f.HostFactory(room=None) - - -def test_user_host_without_room(client, host_without_room): - resp = client.assert_url_ok( - url_for("host.user_hosts_json", user_id=host_without_room.owner.id) - ) - assert len(resp.json["items"]) == 1 - [it] = resp.json["items"] - assert it["switch"] is None - assert it["port"] is None - - @pytest.mark.usefixtures("session") class TestInterfaceDelete: def test_delete_nonexistent_interface(self, client): From 11d37b3ec75fdeb8b8986eb0b43661badf1f83f7 Mon Sep 17 00:00:00 2001 From: Lukas Juhrich Date: Thu, 29 Jun 2023 20:29:00 +0200 Subject: [PATCH 14/14] [tests] test interface manufacturer #641 --- tests/frontend/test_interface.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/frontend/test_interface.py b/tests/frontend/test_interface.py index 4e48cbe26..7459bd30d 100644 --- a/tests/frontend/test_interface.py +++ b/tests/frontend/test_interface.py @@ -136,3 +136,19 @@ def test_create_interface_success(self, client, host): method="POST", data={"mac": "00:11:22:33:44:55", "name": "new name"}, ) + + +class TestManufacturer: + def test_manufacturer_invalid_mac(self, client): + client.assert_url_response_code( + url_for("host.interface_manufacturer_json", mac="invalid"), code=400 + ) + + def test_manufacturer_valid_mac(self, client, monkeypatch): + monkeypatch.setattr( + "web.blueprints.host.get_interface_manufacturer", lambda mac: "AG DSN" + ) + resp = client.assert_url_ok( + url_for("host.interface_manufacturer_json", mac="00:11:22:33:44:55") + ) + assert resp.json["manufacturer"] == "AG DSN"