diff --git a/tests_integration/tests/filament/__init__.py b/tests_integration/tests/filament/__init__.py new file mode 100644 index 0000000..45f2e46 --- /dev/null +++ b/tests_integration/tests/filament/__init__.py @@ -0,0 +1 @@ +"""Tests for the filament API.""" diff --git a/tests_integration/tests/filament/test_add.py b/tests_integration/tests/filament/test_add.py new file mode 100644 index 0000000..accb310 --- /dev/null +++ b/tests_integration/tests/filament/test_add.py @@ -0,0 +1,116 @@ +"""Integration tests for the Filament API endpoint.""" + +from typing import Any + +import httpx + +URL = "http://spoolman:8000" + + +def test_add_filament(random_vendor: dict[str, Any]): + """Test adding a filament to the database.""" + # Execute + name = "Filament X" + material = "PLA" + price = 100 + density = 1.25 + diameter = 1.75 + weight = 1000 + spool_weight = 250 + article_number = "123456789" + comment = "abcdefghåäö" + settings_extruder_temp = 200 + settings_bed_temp = 60 + color_hex = "FF0000" + result = httpx.post( + f"{URL}/api/v1/filament", + json={ + "name": name, + "vendor_id": random_vendor["id"], + "material": material, + "price": price, + "density": density, + "diameter": diameter, + "weight": weight, + "spool_weight": spool_weight, + "article_number": article_number, + "comment": comment, + "settings_extruder_temp": settings_extruder_temp, + "settings_bed_temp": settings_bed_temp, + "color_hex": color_hex, + }, + ) + result.raise_for_status() + + # Verify + filament = result.json() + assert filament == { + "id": filament["id"], + "registered": filament["registered"], + "name": name, + "vendor": random_vendor, + "material": material, + "price": price, + "density": density, + "diameter": diameter, + "weight": weight, + "spool_weight": spool_weight, + "article_number": article_number, + "comment": comment, + "settings_extruder_temp": settings_extruder_temp, + "settings_bed_temp": settings_bed_temp, + "color_hex": color_hex, + } + + # Clean up + httpx.delete(f"{URL}/api/v1/filament/{filament['id']}").raise_for_status() + + +def test_add_filament_required(): + """Test adding a filament with only the required fields to the database.""" + # Execute + density = 1.25 + diameter = 1.75 + result = httpx.post( + f"{URL}/api/v1/filament", + json={ + "density": density, + "diameter": diameter, + }, + ) + result.raise_for_status() + + # Verify + filament = result.json() + assert filament == { + "id": filament["id"], + "registered": filament["registered"], + "density": density, + "diameter": diameter, + } + + # Clean up + httpx.delete(f"{URL}/api/v1/filament/{filament['id']}").raise_for_status() + + +def test_add_filament_color_hex_alpha(): + """Test adding a filament with an alpha channel in the color hex.""" + color_hex = "FF000088" + + # Execute + result = httpx.post( + f"{URL}/api/v1/filament", + json={ + "density": 1.25, + "diameter": 1.75, + "color_hex": color_hex, + }, + ) + result.raise_for_status() + + # Verify + filament = result.json() + assert filament["color_hex"] == color_hex + + # Clean up + httpx.delete(f"{URL}/api/v1/filament/{filament['id']}").raise_for_status() diff --git a/tests_integration/tests/filament/test_delete.py b/tests_integration/tests/filament/test_delete.py new file mode 100644 index 0000000..ec9a275 --- /dev/null +++ b/tests_integration/tests/filament/test_delete.py @@ -0,0 +1,53 @@ +"""Integration tests for the Filament API endpoint.""" + +from typing import Any + +import httpx + +URL = "http://spoolman:8000" + + +def test_delete_filament(random_vendor: dict[str, Any]): + """Test deleting a filament from the database.""" + # Setup + result = httpx.post( + f"{URL}/api/v1/filament", + json={ + "name": "Filament X", + "vendor_id": random_vendor["id"], + "material": "PLA", + "price": 100, + "density": 1.25, + "diameter": 1.75, + "weight": 1000, + "spool_weight": 250, + "article_number": "123456789", + "comment": "abcdefghåäö", + }, + ) + result.raise_for_status() + added_filament = result.json() + + # Execute + httpx.delete( + f"{URL}/api/v1/filament/{added_filament['id']}", + ).raise_for_status() + + # Verify + result = httpx.get( + f"{URL}/api/v1/filament/{added_filament['id']}", + ) + assert result.status_code == 404 + + +def test_delete_filament_not_found(): + """Test deleting a filament that does not exist.""" + # Execute + result = httpx.delete(f"{URL}/api/v1/filament/123456789") + + # Verify + assert result.status_code == 404 + message = result.json()["message"].lower() + assert "filament" in message + assert "id" in message + assert "123456789" in message diff --git a/tests_integration/tests/filament/test_find.py b/tests_integration/tests/filament/test_find.py new file mode 100644 index 0000000..a833add --- /dev/null +++ b/tests_integration/tests/filament/test_find.py @@ -0,0 +1,130 @@ +"""Integration tests for the Filament API endpoint.""" + +from typing import Any + +import httpx + +URL = "http://spoolman:8000" + + +def test_find_filaments(random_vendor: dict[str, Any]): + """Test finding filaments from the database.""" + # Setup + result = httpx.post( + f"{URL}/api/v1/filament", + json={ + "name": "Filament X", + "vendor_id": random_vendor["id"], + "material": "PLA", + "price": 100, + "density": 1.25, + "diameter": 1.75, + "weight": 1000, + "spool_weight": 250, + "article_number": "123456789", + "comment": "abcdefghåäö", + }, + ) + result.raise_for_status() + filament_1 = result.json() + + result = httpx.post( + f"{URL}/api/v1/filament", + json={ + "name": "Filament Y", + "vendor_id": random_vendor["id"], + "material": "ABS", + "price": 200, + "density": 1.25, + "diameter": 1.75, + "weight": 1000, + "spool_weight": 250, + "article_number": "987654321", + "comment": "abcdefghåäö", + }, + ) + result.raise_for_status() + filament_2 = result.json() + + added_filaments_by_id = { + filament_1["id"]: filament_1, + filament_2["id"]: filament_2, + } + + # Execute - find all filaments + result = httpx.get( + f"{URL}/api/v1/filament", + ) + result.raise_for_status() + + # Verify + filaments = result.json() + assert len(filaments) == 2 + for filament in filaments: + assert filament == added_filaments_by_id[filament["id"]] + + # Execute - find filaments by name + result = httpx.get( + f"{URL}/api/v1/filament", + params={"name": "Filament X"}, + ) + result.raise_for_status() + + # Verify + filaments = result.json() + assert len(filaments) == 1 + assert filaments[0] == added_filaments_by_id[filament_1["id"]] + + # Execute - find filaments by material + result = httpx.get( + f"{URL}/api/v1/filament", + params={"material": "abs"}, + ) + result.raise_for_status() + + # Verify + filaments = result.json() + assert len(filaments) == 1 + assert filaments[0] == added_filaments_by_id[filament_2["id"]] + + # Execute - find filaments by vendor id + result = httpx.get( + f"{URL}/api/v1/filament", + params={"vendor_id": random_vendor["id"]}, + ) + result.raise_for_status() + + # Verify + filaments = result.json() + assert len(filaments) == 2 + for filament in filaments: + assert filament == added_filaments_by_id[filament["id"]] + + # Execute - find filaments by vendor name + result = httpx.get( + f"{URL}/api/v1/filament", + params={"vendor_name": random_vendor["name"]}, + ) + result.raise_for_status() + + # Verify + filaments = result.json() + assert len(filaments) == 2 + for filament in filaments: + assert filament == added_filaments_by_id[filament["id"]] + + # Execute - find filaments by article number + result = httpx.get( + f"{URL}/api/v1/filament", + params={"article_number": "321"}, + ) + result.raise_for_status() + + # Verify + filaments = result.json() + assert len(filaments) == 1 + assert filaments[0] == added_filaments_by_id[filament_2["id"]] + + # Clean up + httpx.delete(f"{URL}/api/v1/filament/{filament_1['id']}").raise_for_status() + httpx.delete(f"{URL}/api/v1/filament/{filament_2['id']}").raise_for_status() diff --git a/tests_integration/tests/filament/test_get.py b/tests_integration/tests/filament/test_get.py new file mode 100644 index 0000000..604fc3c --- /dev/null +++ b/tests_integration/tests/filament/test_get.py @@ -0,0 +1,88 @@ +"""Integration tests for the Filament API endpoint.""" + +from typing import Any + +import httpx + +URL = "http://spoolman:8000" + + +def test_get_filament(random_vendor: dict[str, Any]): + """Test getting a filament from the database.""" + # Setup + name = "Filament X" + material = "PLA" + price = 100 + density = 1.25 + diameter = 1.75 + weight = 1000 + spool_weight = 250 + article_number = "123456789" + comment = "abcdefghåäö" + settings_extruder_temp = 200 + settings_bed_temp = 60 + color_hex = "FF0000" + result = httpx.post( + f"{URL}/api/v1/filament", + json={ + "name": name, + "vendor_id": random_vendor["id"], + "material": material, + "price": price, + "density": density, + "diameter": diameter, + "weight": weight, + "spool_weight": spool_weight, + "article_number": article_number, + "comment": comment, + "settings_extruder_temp": settings_extruder_temp, + "settings_bed_temp": settings_bed_temp, + "color_hex": color_hex, + }, + ) + result.raise_for_status() + added_filament = result.json() + + # Execute + result = httpx.get( + f"{URL}/api/v1/filament/{added_filament['id']}", + ) + result.raise_for_status() + + # Verify + filament = result.json() + assert filament == { + "id": added_filament["id"], + "registered": added_filament["registered"], + "name": name, + "vendor": random_vendor, + "material": material, + "price": price, + "density": density, + "diameter": diameter, + "weight": weight, + "spool_weight": spool_weight, + "article_number": article_number, + "comment": comment, + "settings_extruder_temp": settings_extruder_temp, + "settings_bed_temp": settings_bed_temp, + "color_hex": color_hex, + } + + # Clean up + httpx.delete(f"{URL}/api/v1/filament/{filament['id']}").raise_for_status() + + +def test_get_filament_not_found(): + """Test getting a filament that does not exist.""" + # Execute + result = httpx.get( + f"{URL}/api/v1/filament/123456789", + ) + + # Verify + assert result.status_code == 404 + message = result.json()["message"].lower() + assert "filament" in message + assert "id" in message + assert "123456789" in message diff --git a/tests_integration/tests/filament/test_update.py b/tests_integration/tests/filament/test_update.py new file mode 100644 index 0000000..a1cff92 --- /dev/null +++ b/tests_integration/tests/filament/test_update.py @@ -0,0 +1,104 @@ +"""Integration tests for the Filament API endpoint.""" + +from typing import Any + +import httpx + +URL = "http://spoolman:8000" + + +def test_update_filament(random_vendor: dict[str, Any]): + """Test updating a filament in the database.""" + # Setup + result = httpx.post( + f"{URL}/api/v1/filament", + json={ + "name": "Filament X", + "vendor_id": random_vendor["id"], + "material": "PLA", + "price": 100, + "density": 1.25, + "diameter": 1.75, + "weight": 1000, + "spool_weight": 250, + "article_number": "123456789", + "comment": "abcdefghåäö", + "settings_extruder_temp": 200, + "settings_bed_temp": 60, + "color_hex": "FF0000", + }, + ) + result.raise_for_status() + added_filament = result.json() + + # Execute + new_name = "Filament Y" + new_material = "ABS" + new_price = 200 + new_density = 4.2 + new_diameter = 0.12 + new_weight = 5431 + new_spool_weight = 123 + new_article_number = "987654321" + new_comment = "test" + new_settings_extruder_temp = 210 + new_settings_bed_temp = 70 + new_color_hex = "00FF00" + result = httpx.patch( + f"{URL}/api/v1/filament/{added_filament['id']}", + json={ + "name": new_name, + "vendor_id": random_vendor["id"], + "material": new_material, + "price": new_price, + "density": new_density, + "diameter": new_diameter, + "weight": new_weight, + "spool_weight": new_spool_weight, + "article_number": new_article_number, + "comment": new_comment, + "settings_extruder_temp": new_settings_extruder_temp, + "settings_bed_temp": new_settings_bed_temp, + "color_hex": new_color_hex, + }, + ) + result.raise_for_status() + + # Verify + filament = result.json() + assert filament == { + "id": added_filament["id"], + "registered": added_filament["registered"], + "name": new_name, + "vendor": random_vendor, + "material": new_material, + "price": new_price, + "density": new_density, + "diameter": new_diameter, + "weight": new_weight, + "spool_weight": new_spool_weight, + "article_number": new_article_number, + "comment": new_comment, + "settings_extruder_temp": new_settings_extruder_temp, + "settings_bed_temp": new_settings_bed_temp, + "color_hex": new_color_hex, + } + + # Clean up + httpx.delete(f"{URL}/api/v1/filament/{filament['id']}").raise_for_status() + + +def test_update_filament_not_found(): + """Test updating a filament that does not exist.""" + # Execute + result = httpx.patch( + f"{URL}/api/v1/filament/123456789", + json={"name": "Filament Y"}, + ) + + # Verify + assert result.status_code == 404 + message = result.json()["message"].lower() + assert "filament" in message + assert "id" in message + assert "123456789" in message diff --git a/tests_integration/tests/spool/__init__.py b/tests_integration/tests/spool/__init__.py new file mode 100644 index 0000000..db10685 --- /dev/null +++ b/tests_integration/tests/spool/__init__.py @@ -0,0 +1 @@ +"""Tests for the spool API.""" diff --git a/tests_integration/tests/spool/test_add.py b/tests_integration/tests/spool/test_add.py new file mode 100644 index 0000000..e9eb1b9 --- /dev/null +++ b/tests_integration/tests/spool/test_add.py @@ -0,0 +1,182 @@ +"""Integration tests for the Spool API endpoint.""" + +from typing import Any + +import httpx +import pytest + +from tests.conftest import length_from_weight + +URL = "http://spoolman:8000" + + +def test_add_spool_remaining_weight(random_filament: dict[str, Any]): + """Test adding a spool to the database.""" + # Execute + remaining_weight = 750 + location = "The Pantry" + lot_nr = "123456789" + comment = "abcdefghåäö" + archived = True + result = httpx.post( + f"{URL}/api/v1/spool", + json={ + "first_used": "2023-01-02T12:00:00+01:00", + "last_used": "2023-01-02T11:00:00Z", + "filament_id": random_filament["id"], + "remaining_weight": remaining_weight, + "location": location, + "lot_nr": lot_nr, + "comment": comment, + "archived": archived, + }, + ) + result.raise_for_status() + + # Verify + used_weight = random_filament["weight"] - remaining_weight + used_length = length_from_weight( + weight=used_weight, + density=random_filament["density"], + diameter=random_filament["diameter"], + ) + remaining_length = length_from_weight( + weight=remaining_weight, + density=random_filament["density"], + diameter=random_filament["diameter"], + ) + + spool = result.json() + assert spool == { + "id": spool["id"], + "registered": spool["registered"], + "first_used": "2023-01-02T11:00:00", + "last_used": "2023-01-02T11:00:00", + "filament": random_filament, + "remaining_weight": pytest.approx(remaining_weight), + "used_weight": pytest.approx(used_weight), + "remaining_length": pytest.approx(remaining_length), + "used_length": pytest.approx(used_length), + "location": location, + "lot_nr": lot_nr, + "comment": comment, + "archived": archived, + } + + # Clean up + httpx.delete(f"{URL}/api/v1/spool/{spool['id']}").raise_for_status() + + +def test_add_spool_used_weight(random_filament: dict[str, Any]): + """Test adding a spool to the database.""" + # Execute + first_used = "2023-01-01T00:00:00" + last_used = "2023-01-02T00:00:00" + used_weight = 250 + location = "The Pantry" + lot_nr = "123456789" + comment = "abcdefghåäö" + archived = True + result = httpx.post( + f"{URL}/api/v1/spool", + json={ + "first_used": first_used, + "last_used": last_used, + "filament_id": random_filament["id"], + "used_weight": used_weight, + "location": location, + "lot_nr": lot_nr, + "comment": comment, + "archived": archived, + }, + ) + result.raise_for_status() + + # Verify + remaining_weight = random_filament["weight"] - used_weight + used_length = length_from_weight( + weight=used_weight, + density=random_filament["density"], + diameter=random_filament["diameter"], + ) + remaining_length = length_from_weight( + weight=remaining_weight, + density=random_filament["density"], + diameter=random_filament["diameter"], + ) + + spool = result.json() + assert spool == { + "id": spool["id"], + "registered": spool["registered"], + "first_used": first_used, + "last_used": last_used, + "filament": random_filament, + "remaining_weight": pytest.approx(remaining_weight), + "used_weight": pytest.approx(used_weight), + "remaining_length": pytest.approx(remaining_length), + "used_length": pytest.approx(used_length), + "location": location, + "lot_nr": lot_nr, + "comment": comment, + "archived": archived, + } + + # Clean up + httpx.delete(f"{URL}/api/v1/spool/{spool['id']}").raise_for_status() + + +def test_add_spool_required(random_filament: dict[str, Any]): + """Test adding a spool with only the required fields to the database.""" + # Execute + used_weight = 250 + result = httpx.post( + f"{URL}/api/v1/spool", + json={ + "filament_id": random_filament["id"], + "used_weight": used_weight, + }, + ) + result.raise_for_status() + + # Verify + remaining_weight = random_filament["weight"] - used_weight + used_length = length_from_weight( + weight=used_weight, + density=random_filament["density"], + diameter=random_filament["diameter"], + ) + remaining_length = length_from_weight( + weight=remaining_weight, + density=random_filament["density"], + diameter=random_filament["diameter"], + ) + + spool = result.json() + assert spool == { + "id": spool["id"], + "registered": spool["registered"], + "filament": random_filament, + "used_weight": pytest.approx(used_weight), + "remaining_weight": pytest.approx(remaining_weight), + "used_length": pytest.approx(used_length), + "remaining_length": pytest.approx(remaining_length), + "archived": False, + } + + # Clean up + httpx.delete(f"{URL}/api/v1/spool/{spool['id']}").raise_for_status() + + +def test_add_spool_both_used_and_remaining_weight(random_filament: dict[str, Any]): + """Test adding a spool to the database.""" + # Execute + result = httpx.post( + f"{URL}/api/v1/spool", + json={ + "filament_id": random_filament["id"], + "remaining_weight": 750, + "used_weight": 250, + }, + ) + assert result.status_code == 400 # Cannot set both used and remaining weight diff --git a/tests_integration/tests/spool/test_delete.py b/tests_integration/tests/spool/test_delete.py new file mode 100644 index 0000000..56b7b04 --- /dev/null +++ b/tests_integration/tests/spool/test_delete.py @@ -0,0 +1,43 @@ +"""Integration tests for the Spool API endpoint.""" + +from typing import Any + +import httpx + +URL = "http://spoolman:8000" + + +def test_delete_spool(random_filament: dict[str, Any]): + """Test deleting a spool from the database.""" + # Setup + result = httpx.post( + f"{URL}/api/v1/spool", + json={ + "filament_id": random_filament["id"], + "remaining_weight": 1000, + "location": "The Pantry", + "lot_nr": "123456789", + }, + ) + result.raise_for_status() + spool = result.json() + + # Execute + httpx.delete(f"{URL}/api/v1/spool/{spool['id']}").raise_for_status() + + # Verify + result = httpx.get(f"{URL}/api/v1/spool/{spool['id']}") + assert result.status_code == 404 + + +def test_delete_spool_not_found(): + """Test deleting a spool that does not exist.""" + # Execute + result = httpx.delete(f"{URL}/api/v1/spool/123456789") + + # Verify + assert result.status_code == 404 + message = result.json()["message"].lower() + assert "spool" in message + assert "id" in message + assert "123456789" in message diff --git a/tests_integration/tests/spool/test_find.py b/tests_integration/tests/spool/test_find.py new file mode 100644 index 0000000..65e48ff --- /dev/null +++ b/tests_integration/tests/spool/test_find.py @@ -0,0 +1,167 @@ +"""Integration tests for the Spool API endpoint.""" + +from typing import Any + +import httpx + +URL = "http://spoolman:8000" + + +def test_find_spools(random_filament: dict[str, Any]): # noqa: PLR0915 + """Test finding spools in the database.""" + # Setup + result = httpx.post( + f"{URL}/api/v1/spool", + json={ + "filament_id": random_filament["id"], + "remaining_weight": 1000, + "location": "The Pantry", + "lot_nr": "123456789", + }, + ) + result.raise_for_status() + spool_1 = result.json() + + result = httpx.post( + f"{URL}/api/v1/spool", + json={ + "filament_id": random_filament["id"], + "remaining_weight": 1000, + "location": "Living Room", + "lot_nr": "987654321", + }, + ) + result.raise_for_status() + spool_2 = result.json() + + result = httpx.post( + f"{URL}/api/v1/spool", + json={ + "filament_id": random_filament["id"], + "remaining_weight": 1000, + "archived": True, + }, + ) + result.raise_for_status() + spool_3 = result.json() + + added_spools_by_id = { + spool_1["id"]: spool_1, + spool_2["id"]: spool_2, + spool_3["id"]: spool_3, + } + + # Execute - find all spools + result = httpx.get(f"{URL}/api/v1/spool") + result.raise_for_status() + + # Verify + spools = result.json() + assert len(spools) == 2 + for spool in spools: + assert spool == added_spools_by_id[spool["id"]] + assert spool["archived"] is False + + # Execute - find all spools, including archived + result = httpx.get(f"{URL}/api/v1/spool?allow_archived=true") + result.raise_for_status() + + # Verify + spools = result.json() + assert len(spools) == 3 + for spool in spools: + assert spool == added_spools_by_id[spool["id"]] + + # Execute - find spools by filament name + result = httpx.get( + f"{URL}/api/v1/spool", + params={"filament_name": random_filament["name"]}, + ) + result.raise_for_status() + + # Verify + spools = result.json() + assert len(spools) == 2 + for spool in spools: + assert spool == added_spools_by_id[spool["id"]] + + # Execute - find spools by filament id + result = httpx.get( + f"{URL}/api/v1/spool", + params={"filament_id": random_filament["id"]}, + ) + result.raise_for_status() + + # Verify + spools = result.json() + assert len(spools) == 2 + for spool in spools: + assert spool == added_spools_by_id[spool["id"]] + + # Execute - find spools by filament material + result = httpx.get( + f"{URL}/api/v1/spool", + params={"filament_material": random_filament["material"]}, + ) + result.raise_for_status() + + # Verify + spools = result.json() + assert len(spools) == 2 + for spool in spools: + assert spool == added_spools_by_id[spool["id"]] + + # Execute - find spools by filament vendor name + result = httpx.get( + f"{URL}/api/v1/spool", + params={"vendor_name": random_filament["vendor"]["name"]}, + ) + result.raise_for_status() + + # Verify + spools = result.json() + assert len(spools) == 2 + for spool in spools: + assert spool == added_spools_by_id[spool["id"]] + + # Execute - find spools by filament vendor id + result = httpx.get( + f"{URL}/api/v1/spool", + params={"vendor_id": random_filament["vendor"]["id"]}, + ) + result.raise_for_status() + + # Verify + spools = result.json() + assert len(spools) == 2 + for spool in spools: + assert spool == added_spools_by_id[spool["id"]] + + # Execute - find spools by location + result = httpx.get( + f"{URL}/api/v1/spool", + params={"location": "The Pantry"}, + ) + result.raise_for_status() + + # Verify + spools = result.json() + assert len(spools) == 1 + assert spools[0] == added_spools_by_id[spool_1["id"]] + + # Execute - find spools by lot nr + result = httpx.get( + f"{URL}/api/v1/spool", + params={"lot_nr": "123456789"}, + ) + result.raise_for_status() + + # Verify + spools = result.json() + assert len(spools) == 1 + assert spools[0] == added_spools_by_id[spool_1["id"]] + + # Clean up + httpx.delete(f"{URL}/api/v1/spool/{spool_1['id']}").raise_for_status() + httpx.delete(f"{URL}/api/v1/spool/{spool_2['id']}").raise_for_status() + httpx.delete(f"{URL}/api/v1/spool/{spool_3['id']}").raise_for_status() diff --git a/tests_integration/tests/spool/test_get.py b/tests_integration/tests/spool/test_get.py new file mode 100644 index 0000000..acb8345 --- /dev/null +++ b/tests_integration/tests/spool/test_get.py @@ -0,0 +1,57 @@ +"""Integration tests for the Spool API endpoint.""" + +from typing import Any + +import httpx + +URL = "http://spoolman:8000" + + +def test_get_spool(random_filament: dict[str, Any]): + """Test getting a spool from the database.""" + # Setup + first_used = "2023-01-01T00:00:00" + last_used = "2023-01-02T00:00:00" + remaining_weight = 750 + location = "The Pantry" + lot_nr = "123456789" + comment = "abcdefghåäö" + archived = True + result = httpx.post( + f"{URL}/api/v1/spool", + json={ + "first_used": first_used, + "last_used": last_used, + "filament_id": random_filament["id"], + "remaining_weight": remaining_weight, + "location": location, + "lot_nr": lot_nr, + "comment": comment, + "archived": archived, + }, + ) + result.raise_for_status() + spool = result.json() + + # Execute + result = httpx.get(f"{URL}/api/v1/spool/{spool['id']}") + result.raise_for_status() + + # Verify + assert result.json() == spool + + # Clean up + httpx.delete(f"{URL}/api/v1/spool/{spool['id']}").raise_for_status() + + +def test_get_spool_not_found(): + """Test getting a spool that does not exist.""" + # Execute + result = httpx.get(f"{URL}/api/v1/spool/123456789") + + # Verify + assert result.status_code == 404 + message = result.json()["message"].lower() + assert "spool" in message + assert "id" in message + assert "123456789" in message diff --git a/tests_integration/tests/spool/test_update.py b/tests_integration/tests/spool/test_update.py new file mode 100644 index 0000000..a140346 --- /dev/null +++ b/tests_integration/tests/spool/test_update.py @@ -0,0 +1,114 @@ +"""Integration tests for the Spool API endpoint.""" + +from typing import Any + +import httpx +import pytest + +from tests.conftest import length_from_weight + +URL = "http://spoolman:8000" + + +def test_update_spool(random_filament: dict[str, Any]): + """Test updating a spool in the database.""" + # Setup + result = httpx.post( + f"{URL}/api/v1/spool", + json={ + "filament_id": random_filament["id"], + "remaining_weight": 1000, + "location": "The Pantry", + "lot_nr": "123456789", + }, + ) + result.raise_for_status() + spool = result.json() + + # Execute + first_used = "2023-01-01T12:00:00+02:00" + last_used = "2023-01-02T12:00:00+02:00" + remaining_weight = 750 + location = "Living Room" + lot_nr = "987654321" + comment = "abcdefghåäö" + archived = True + result = httpx.patch( + f"{URL}/api/v1/spool/{spool['id']}", + json={ + "first_used": first_used, + "last_used": last_used, + "remaining_weight": remaining_weight, + "location": location, + "lot_nr": lot_nr, + "comment": comment, + "archived": archived, + }, + ) + result.raise_for_status() + + # Verify + used_weight = random_filament["weight"] - remaining_weight + used_length = length_from_weight( + weight=used_weight, + density=random_filament["density"], + diameter=random_filament["diameter"], + ) + remaining_length = length_from_weight( + weight=remaining_weight, + density=random_filament["density"], + diameter=random_filament["diameter"], + ) + + spool = result.json() + assert spool["first_used"] == "2023-01-01T10:00:00" + assert spool["last_used"] == "2023-01-02T10:00:00" + assert spool["remaining_weight"] == pytest.approx(remaining_weight) + assert spool["used_weight"] == pytest.approx(used_weight) + assert spool["remaining_length"] == pytest.approx(remaining_length) + assert spool["used_length"] == pytest.approx(used_length) + assert spool["location"] == location + assert spool["lot_nr"] == lot_nr + assert spool["comment"] == comment + assert spool["archived"] == archived + + # Clean up + httpx.delete(f"{URL}/api/v1/spool/{spool['id']}").raise_for_status() + + +def test_update_spool_both_used_and_remaining_weight(random_filament: dict[str, Any]): + """Test updating a spool in the database.""" + # Setup + result = httpx.post( + f"{URL}/api/v1/spool", + json={"filament_id": random_filament["id"]}, + ) + result.raise_for_status() + spool = result.json() + + # Execute + result = httpx.patch( + f"{URL}/api/v1/spool/{spool['id']}", + json={ + "remaining_weight": 750, + "used_weight": 250, + }, + ) + assert result.status_code == 400 # Cannot update both used and remaining weight + + # Clean up + httpx.delete(f"{URL}/api/v1/spool/{spool['id']}").raise_for_status() + + +def test_update_spool_not_found(random_filament: dict[str, Any]): + """Test updating a spool that does not exist.""" + # Execute + result = httpx.patch( + f"{URL}/api/v1/spool/123456789", + json={"filament_id": random_filament["id"]}, + ) + assert result.status_code == 404 + message = result.json()["message"].lower() + assert "spool" in message + assert "id" in message + assert "123456789" in message diff --git a/tests_integration/tests/spool/test_use.py b/tests_integration/tests/spool/test_use.py new file mode 100644 index 0000000..42a5d5d --- /dev/null +++ b/tests_integration/tests/spool/test_use.py @@ -0,0 +1,163 @@ +"""Integration tests for the Spool API endpoint.""" + +import asyncio +import math +from typing import Any + +import httpx +import pytest + +URL = "http://spoolman:8000" + + +@pytest.mark.parametrize("use_weight", [0, 0.05, -0.05, 1500]) # 1500 is big enough to use all filament +def test_use_spool_weight(random_filament: dict[str, Any], use_weight: float): + """Test using a spool in the database.""" + # Setup + filament_net_weight = random_filament["weight"] + start_weight = 1000 + result = httpx.post( + f"{URL}/api/v1/spool", + json={ + "filament_id": random_filament["id"], + "remaining_weight": start_weight, + }, + ) + result.raise_for_status() + spool = result.json() + + # Execute + result = httpx.put( + f"{URL}/api/v1/spool/{spool['id']}/use", + json={ + "use_weight": use_weight, + }, + ) + result.raise_for_status() + + # Verify + spool = result.json() + # remaining_weight should be clamped so it's never negative, but used_weight should not be clamped to the net weight + assert spool["used_weight"] == pytest.approx(max(use_weight, 0)) + assert spool["remaining_weight"] == pytest.approx(min(max(start_weight - use_weight, 0), filament_net_weight)) + + # Clean up + httpx.delete(f"{URL}/api/v1/spool/{spool['id']}").raise_for_status() + + +@pytest.mark.parametrize("use_length", [0, 10, -10, 500e3]) # 500e3 is big enough to use all the filament +def test_use_spool_length(random_filament: dict[str, Any], use_length: float): + """Test using a spool in the database.""" + # Setup + filament_net_weight = random_filament["weight"] + start_weight = 1000 + result = httpx.post( + f"{URL}/api/v1/spool", + json={ + "filament_id": random_filament["id"], + "remaining_weight": start_weight, + }, + ) + result.raise_for_status() + spool = result.json() + + # Execute + result = httpx.put( + f"{URL}/api/v1/spool/{spool['id']}/use", + json={ + "use_length": use_length, + }, + ) + result.raise_for_status() + + # Verify + spool = result.json() + use_weight = ( + random_filament["density"] * (use_length * 1e-1) * math.pi * ((random_filament["diameter"] * 1e-1 / 2) ** 2) + ) + # remaining_weight should be clamped so it's never negative, but used_weight should not be clamped to the net weight + assert spool["used_weight"] == pytest.approx(max(use_weight, 0)) + assert spool["remaining_weight"] == pytest.approx(min(max(start_weight - use_weight, 0), filament_net_weight)) + + # Clean up + httpx.delete(f"{URL}/api/v1/spool/{spool['id']}").raise_for_status() + + +def test_use_spool_weight_and_length(random_filament: dict[str, Any]): + """Test using a spool in the database.""" + # Setup + result = httpx.post( + f"{URL}/api/v1/spool", + json={"filament_id": random_filament["id"]}, + ) + result.raise_for_status() + spool = result.json() + + # Execute + result = httpx.put( + f"{URL}/api/v1/spool/{spool['id']}/use", + json={ + "use_weight": 0.05, + "use_length": 10, + }, + ) + assert result.status_code == 400 # Cannot use both weight and length + + # Clean up + httpx.delete(f"{URL}/api/v1/spool/{spool['id']}").raise_for_status() + + +def test_use_spool_not_found(): + """Test using a spool that does not exist.""" + # Execute + result = httpx.put( + f"{URL}/api/v1/spool/123456789/use", + json={"use_weight": 0.05}, + ) + assert result.status_code == 404 + message = result.json()["message"].lower() + assert "spool" in message + assert "id" in message + assert "123456789" in message + + +@pytest.mark.asyncio() +async def test_use_spool_concurrent(random_filament: dict[str, Any]): + """Test using a spool with many concurrent requests.""" + # Setup + start_weight = 1000 + result = httpx.post( # noqa: ASYNC100 + f"{URL}/api/v1/spool", + json={ + "filament_id": random_filament["id"], + "remaining_weight": start_weight, + }, + ) + result.raise_for_status() + spool = result.json() + + # Execute + requests = 100 + used_weight = 0.5 + async with httpx.AsyncClient() as client: + await asyncio.gather( + *( + client.put( + f"{URL}/api/v1/spool/{spool['id']}/use", + json={ + "use_weight": used_weight, + }, + timeout=60, + ) + for _ in range(requests) + ), + ) + + # Verify + result = httpx.get(f"{URL}/api/v1/spool/{spool['id']}") # noqa: ASYNC100 + result.raise_for_status() + spool = result.json() + assert spool["remaining_weight"] == pytest.approx(start_weight - (used_weight * requests)) + + # Clean up + httpx.delete(f"{URL}/api/v1/spool/{spool['id']}").raise_for_status() # noqa: ASYNC100 diff --git a/tests_integration/tests/test_filament.py b/tests_integration/tests/test_filament.py deleted file mode 100644 index eebb7f6..0000000 --- a/tests_integration/tests/test_filament.py +++ /dev/null @@ -1,460 +0,0 @@ -"""Integration tests for the Filament API endpoint.""" - -from typing import Any - -import httpx - -URL = "http://spoolman:8000" - - -def test_add_filament(random_vendor: dict[str, Any]): - """Test adding a filament to the database.""" - # Execute - name = "Filament X" - material = "PLA" - price = 100 - density = 1.25 - diameter = 1.75 - weight = 1000 - spool_weight = 250 - article_number = "123456789" - comment = "abcdefghåäö" - settings_extruder_temp = 200 - settings_bed_temp = 60 - color_hex = "FF0000" - result = httpx.post( - f"{URL}/api/v1/filament", - json={ - "name": name, - "vendor_id": random_vendor["id"], - "material": material, - "price": price, - "density": density, - "diameter": diameter, - "weight": weight, - "spool_weight": spool_weight, - "article_number": article_number, - "comment": comment, - "settings_extruder_temp": settings_extruder_temp, - "settings_bed_temp": settings_bed_temp, - "color_hex": color_hex, - }, - ) - result.raise_for_status() - - # Verify - filament = result.json() - assert filament == { - "id": filament["id"], - "registered": filament["registered"], - "name": name, - "vendor": random_vendor, - "material": material, - "price": price, - "density": density, - "diameter": diameter, - "weight": weight, - "spool_weight": spool_weight, - "article_number": article_number, - "comment": comment, - "settings_extruder_temp": settings_extruder_temp, - "settings_bed_temp": settings_bed_temp, - "color_hex": color_hex, - } - - # Clean up - httpx.delete(f"{URL}/api/v1/filament/{filament['id']}").raise_for_status() - - -def test_add_filament_required(): - """Test adding a filament with only the required fields to the database.""" - # Execute - density = 1.25 - diameter = 1.75 - result = httpx.post( - f"{URL}/api/v1/filament", - json={ - "density": density, - "diameter": diameter, - }, - ) - result.raise_for_status() - - # Verify - filament = result.json() - assert filament == { - "id": filament["id"], - "registered": filament["registered"], - "density": density, - "diameter": diameter, - } - - # Clean up - httpx.delete(f"{URL}/api/v1/filament/{filament['id']}").raise_for_status() - - -def test_get_filament(random_vendor: dict[str, Any]): - """Test getting a filament from the database.""" - # Setup - name = "Filament X" - material = "PLA" - price = 100 - density = 1.25 - diameter = 1.75 - weight = 1000 - spool_weight = 250 - article_number = "123456789" - comment = "abcdefghåäö" - settings_extruder_temp = 200 - settings_bed_temp = 60 - color_hex = "FF0000" - result = httpx.post( - f"{URL}/api/v1/filament", - json={ - "name": name, - "vendor_id": random_vendor["id"], - "material": material, - "price": price, - "density": density, - "diameter": diameter, - "weight": weight, - "spool_weight": spool_weight, - "article_number": article_number, - "comment": comment, - "settings_extruder_temp": settings_extruder_temp, - "settings_bed_temp": settings_bed_temp, - "color_hex": color_hex, - }, - ) - result.raise_for_status() - added_filament = result.json() - - # Execute - result = httpx.get( - f"{URL}/api/v1/filament/{added_filament['id']}", - ) - result.raise_for_status() - - # Verify - filament = result.json() - assert filament == { - "id": added_filament["id"], - "registered": added_filament["registered"], - "name": name, - "vendor": random_vendor, - "material": material, - "price": price, - "density": density, - "diameter": diameter, - "weight": weight, - "spool_weight": spool_weight, - "article_number": article_number, - "comment": comment, - "settings_extruder_temp": settings_extruder_temp, - "settings_bed_temp": settings_bed_temp, - "color_hex": color_hex, - } - - # Clean up - httpx.delete(f"{URL}/api/v1/filament/{filament['id']}").raise_for_status() - - -def test_get_filament_not_found(): - """Test getting a filament that does not exist.""" - # Execute - result = httpx.get( - f"{URL}/api/v1/filament/123456789", - ) - - # Verify - assert result.status_code == 404 - message = result.json()["message"].lower() - assert "filament" in message - assert "id" in message - assert "123456789" in message - - -def test_find_filaments(random_vendor: dict[str, Any]): - """Test finding filaments from the database.""" - # Setup - result = httpx.post( - f"{URL}/api/v1/filament", - json={ - "name": "Filament X", - "vendor_id": random_vendor["id"], - "material": "PLA", - "price": 100, - "density": 1.25, - "diameter": 1.75, - "weight": 1000, - "spool_weight": 250, - "article_number": "123456789", - "comment": "abcdefghåäö", - }, - ) - result.raise_for_status() - filament_1 = result.json() - - result = httpx.post( - f"{URL}/api/v1/filament", - json={ - "name": "Filament Y", - "vendor_id": random_vendor["id"], - "material": "ABS", - "price": 200, - "density": 1.25, - "diameter": 1.75, - "weight": 1000, - "spool_weight": 250, - "article_number": "987654321", - "comment": "abcdefghåäö", - }, - ) - result.raise_for_status() - filament_2 = result.json() - - added_filaments_by_id = { - filament_1["id"]: filament_1, - filament_2["id"]: filament_2, - } - - # Execute - find all filaments - result = httpx.get( - f"{URL}/api/v1/filament", - ) - result.raise_for_status() - - # Verify - filaments = result.json() - assert len(filaments) == 2 - for filament in filaments: - assert filament == added_filaments_by_id[filament["id"]] - - # Execute - find filaments by name - result = httpx.get( - f"{URL}/api/v1/filament", - params={"name": "Filament X"}, - ) - result.raise_for_status() - - # Verify - filaments = result.json() - assert len(filaments) == 1 - assert filaments[0] == added_filaments_by_id[filament_1["id"]] - - # Execute - find filaments by material - result = httpx.get( - f"{URL}/api/v1/filament", - params={"material": "abs"}, - ) - result.raise_for_status() - - # Verify - filaments = result.json() - assert len(filaments) == 1 - assert filaments[0] == added_filaments_by_id[filament_2["id"]] - - # Execute - find filaments by vendor id - result = httpx.get( - f"{URL}/api/v1/filament", - params={"vendor_id": random_vendor["id"]}, - ) - result.raise_for_status() - - # Verify - filaments = result.json() - assert len(filaments) == 2 - for filament in filaments: - assert filament == added_filaments_by_id[filament["id"]] - - # Execute - find filaments by vendor name - result = httpx.get( - f"{URL}/api/v1/filament", - params={"vendor_name": random_vendor["name"]}, - ) - result.raise_for_status() - - # Verify - filaments = result.json() - assert len(filaments) == 2 - for filament in filaments: - assert filament == added_filaments_by_id[filament["id"]] - - # Execute - find filaments by article number - result = httpx.get( - f"{URL}/api/v1/filament", - params={"article_number": "321"}, - ) - result.raise_for_status() - - # Verify - filaments = result.json() - assert len(filaments) == 1 - assert filaments[0] == added_filaments_by_id[filament_2["id"]] - - # Clean up - httpx.delete(f"{URL}/api/v1/filament/{filament_1['id']}").raise_for_status() - httpx.delete(f"{URL}/api/v1/filament/{filament_2['id']}").raise_for_status() - - -def test_delete_filament(random_vendor: dict[str, Any]): - """Test deleting a filament from the database.""" - # Setup - result = httpx.post( - f"{URL}/api/v1/filament", - json={ - "name": "Filament X", - "vendor_id": random_vendor["id"], - "material": "PLA", - "price": 100, - "density": 1.25, - "diameter": 1.75, - "weight": 1000, - "spool_weight": 250, - "article_number": "123456789", - "comment": "abcdefghåäö", - }, - ) - result.raise_for_status() - added_filament = result.json() - - # Execute - httpx.delete( - f"{URL}/api/v1/filament/{added_filament['id']}", - ).raise_for_status() - - # Verify - result = httpx.get( - f"{URL}/api/v1/filament/{added_filament['id']}", - ) - assert result.status_code == 404 - - -def test_delete_filament_not_found(): - """Test deleting a filament that does not exist.""" - # Execute - result = httpx.delete(f"{URL}/api/v1/filament/123456789") - - # Verify - assert result.status_code == 404 - message = result.json()["message"].lower() - assert "filament" in message - assert "id" in message - assert "123456789" in message - - -def test_update_filament(random_vendor: dict[str, Any]): - """Test updating a filament in the database.""" - # Setup - result = httpx.post( - f"{URL}/api/v1/filament", - json={ - "name": "Filament X", - "vendor_id": random_vendor["id"], - "material": "PLA", - "price": 100, - "density": 1.25, - "diameter": 1.75, - "weight": 1000, - "spool_weight": 250, - "article_number": "123456789", - "comment": "abcdefghåäö", - "settings_extruder_temp": 200, - "settings_bed_temp": 60, - "color_hex": "FF0000", - }, - ) - result.raise_for_status() - added_filament = result.json() - - # Execute - new_name = "Filament Y" - new_material = "ABS" - new_price = 200 - new_density = 4.2 - new_diameter = 0.12 - new_weight = 5431 - new_spool_weight = 123 - new_article_number = "987654321" - new_comment = "test" - new_settings_extruder_temp = 210 - new_settings_bed_temp = 70 - new_color_hex = "00FF00" - result = httpx.patch( - f"{URL}/api/v1/filament/{added_filament['id']}", - json={ - "name": new_name, - "vendor_id": random_vendor["id"], - "material": new_material, - "price": new_price, - "density": new_density, - "diameter": new_diameter, - "weight": new_weight, - "spool_weight": new_spool_weight, - "article_number": new_article_number, - "comment": new_comment, - "settings_extruder_temp": new_settings_extruder_temp, - "settings_bed_temp": new_settings_bed_temp, - "color_hex": new_color_hex, - }, - ) - result.raise_for_status() - - # Verify - filament = result.json() - assert filament == { - "id": added_filament["id"], - "registered": added_filament["registered"], - "name": new_name, - "vendor": random_vendor, - "material": new_material, - "price": new_price, - "density": new_density, - "diameter": new_diameter, - "weight": new_weight, - "spool_weight": new_spool_weight, - "article_number": new_article_number, - "comment": new_comment, - "settings_extruder_temp": new_settings_extruder_temp, - "settings_bed_temp": new_settings_bed_temp, - "color_hex": new_color_hex, - } - - # Clean up - httpx.delete(f"{URL}/api/v1/filament/{filament['id']}").raise_for_status() - - -def test_update_filament_not_found(): - """Test updating a filament that does not exist.""" - # Execute - result = httpx.patch( - f"{URL}/api/v1/filament/123456789", - json={"name": "Filament Y"}, - ) - - # Verify - assert result.status_code == 404 - message = result.json()["message"].lower() - assert "filament" in message - assert "id" in message - assert "123456789" in message - - -def test_add_filament_color_hex_alpha(): - """Test adding a filament with an alpha channel in the color hex.""" - color_hex = "FF000088" - - # Execute - result = httpx.post( - f"{URL}/api/v1/filament", - json={ - "density": 1.25, - "diameter": 1.75, - "color_hex": color_hex, - }, - ) - result.raise_for_status() - - # Verify - filament = result.json() - assert filament["color_hex"] == color_hex diff --git a/tests_integration/tests/test_spool.py b/tests_integration/tests/test_spool.py deleted file mode 100644 index 0296036..0000000 --- a/tests_integration/tests/test_spool.py +++ /dev/null @@ -1,687 +0,0 @@ -"""Integration tests for the Spool API endpoint.""" - -import asyncio -import math -from typing import Any - -import httpx -import pytest - -from .conftest import length_from_weight - -URL = "http://spoolman:8000" - - -def test_add_spool_remaining_weight(random_filament: dict[str, Any]): - """Test adding a spool to the database.""" - # Execute - remaining_weight = 750 - location = "The Pantry" - lot_nr = "123456789" - comment = "abcdefghåäö" - archived = True - result = httpx.post( - f"{URL}/api/v1/spool", - json={ - "first_used": "2023-01-02T12:00:00+01:00", - "last_used": "2023-01-02T11:00:00Z", - "filament_id": random_filament["id"], - "remaining_weight": remaining_weight, - "location": location, - "lot_nr": lot_nr, - "comment": comment, - "archived": archived, - }, - ) - result.raise_for_status() - - # Verify - used_weight = random_filament["weight"] - remaining_weight - used_length = length_from_weight( - weight=used_weight, - density=random_filament["density"], - diameter=random_filament["diameter"], - ) - remaining_length = length_from_weight( - weight=remaining_weight, - density=random_filament["density"], - diameter=random_filament["diameter"], - ) - - spool = result.json() - assert spool == { - "id": spool["id"], - "registered": spool["registered"], - "first_used": "2023-01-02T11:00:00", - "last_used": "2023-01-02T11:00:00", - "filament": random_filament, - "remaining_weight": pytest.approx(remaining_weight), - "used_weight": pytest.approx(used_weight), - "remaining_length": pytest.approx(remaining_length), - "used_length": pytest.approx(used_length), - "location": location, - "lot_nr": lot_nr, - "comment": comment, - "archived": archived, - } - - # Clean up - httpx.delete(f"{URL}/api/v1/spool/{spool['id']}").raise_for_status() - - -def test_add_spool_used_weight(random_filament: dict[str, Any]): - """Test adding a spool to the database.""" - # Execute - first_used = "2023-01-01T00:00:00" - last_used = "2023-01-02T00:00:00" - used_weight = 250 - location = "The Pantry" - lot_nr = "123456789" - comment = "abcdefghåäö" - archived = True - result = httpx.post( - f"{URL}/api/v1/spool", - json={ - "first_used": first_used, - "last_used": last_used, - "filament_id": random_filament["id"], - "used_weight": used_weight, - "location": location, - "lot_nr": lot_nr, - "comment": comment, - "archived": archived, - }, - ) - result.raise_for_status() - - # Verify - remaining_weight = random_filament["weight"] - used_weight - used_length = length_from_weight( - weight=used_weight, - density=random_filament["density"], - diameter=random_filament["diameter"], - ) - remaining_length = length_from_weight( - weight=remaining_weight, - density=random_filament["density"], - diameter=random_filament["diameter"], - ) - - spool = result.json() - assert spool == { - "id": spool["id"], - "registered": spool["registered"], - "first_used": first_used, - "last_used": last_used, - "filament": random_filament, - "remaining_weight": pytest.approx(remaining_weight), - "used_weight": pytest.approx(used_weight), - "remaining_length": pytest.approx(remaining_length), - "used_length": pytest.approx(used_length), - "location": location, - "lot_nr": lot_nr, - "comment": comment, - "archived": archived, - } - - # Clean up - httpx.delete(f"{URL}/api/v1/spool/{spool['id']}").raise_for_status() - - -def test_add_spool_required(random_filament: dict[str, Any]): - """Test adding a spool with only the required fields to the database.""" - # Execute - used_weight = 250 - result = httpx.post( - f"{URL}/api/v1/spool", - json={ - "filament_id": random_filament["id"], - "used_weight": used_weight, - }, - ) - result.raise_for_status() - - # Verify - remaining_weight = random_filament["weight"] - used_weight - used_length = length_from_weight( - weight=used_weight, - density=random_filament["density"], - diameter=random_filament["diameter"], - ) - remaining_length = length_from_weight( - weight=remaining_weight, - density=random_filament["density"], - diameter=random_filament["diameter"], - ) - - spool = result.json() - assert spool == { - "id": spool["id"], - "registered": spool["registered"], - "filament": random_filament, - "used_weight": pytest.approx(used_weight), - "remaining_weight": pytest.approx(remaining_weight), - "used_length": pytest.approx(used_length), - "remaining_length": pytest.approx(remaining_length), - "archived": False, - } - - # Clean up - httpx.delete(f"{URL}/api/v1/spool/{spool['id']}").raise_for_status() - - -def test_add_spool_both_used_and_remaining_weight(random_filament: dict[str, Any]): - """Test adding a spool to the database.""" - # Execute - result = httpx.post( - f"{URL}/api/v1/spool", - json={ - "filament_id": random_filament["id"], - "remaining_weight": 750, - "used_weight": 250, - }, - ) - assert result.status_code == 400 # Cannot set both used and remaining weight - - -def test_get_spool(random_filament: dict[str, Any]): - """Test getting a spool from the database.""" - # Setup - first_used = "2023-01-01T00:00:00" - last_used = "2023-01-02T00:00:00" - remaining_weight = 750 - location = "The Pantry" - lot_nr = "123456789" - comment = "abcdefghåäö" - archived = True - result = httpx.post( - f"{URL}/api/v1/spool", - json={ - "first_used": first_used, - "last_used": last_used, - "filament_id": random_filament["id"], - "remaining_weight": remaining_weight, - "location": location, - "lot_nr": lot_nr, - "comment": comment, - "archived": archived, - }, - ) - result.raise_for_status() - spool = result.json() - - # Execute - result = httpx.get(f"{URL}/api/v1/spool/{spool['id']}") - result.raise_for_status() - - # Verify - assert result.json() == spool - - # Clean up - httpx.delete(f"{URL}/api/v1/spool/{spool['id']}").raise_for_status() - - -def test_get_spool_not_found(): - """Test getting a spool that does not exist.""" - # Execute - result = httpx.get(f"{URL}/api/v1/spool/123456789") - - # Verify - assert result.status_code == 404 - message = result.json()["message"].lower() - assert "spool" in message - assert "id" in message - assert "123456789" in message - - -def test_find_spools(random_filament: dict[str, Any]): # noqa: PLR0915 - """Test finding spools in the database.""" - # Setup - result = httpx.post( - f"{URL}/api/v1/spool", - json={ - "filament_id": random_filament["id"], - "remaining_weight": 1000, - "location": "The Pantry", - "lot_nr": "123456789", - }, - ) - result.raise_for_status() - spool_1 = result.json() - - result = httpx.post( - f"{URL}/api/v1/spool", - json={ - "filament_id": random_filament["id"], - "remaining_weight": 1000, - "location": "Living Room", - "lot_nr": "987654321", - }, - ) - result.raise_for_status() - spool_2 = result.json() - - result = httpx.post( - f"{URL}/api/v1/spool", - json={ - "filament_id": random_filament["id"], - "remaining_weight": 1000, - "archived": True, - }, - ) - result.raise_for_status() - spool_3 = result.json() - - added_spools_by_id = { - spool_1["id"]: spool_1, - spool_2["id"]: spool_2, - spool_3["id"]: spool_3, - } - - # Execute - find all spools - result = httpx.get(f"{URL}/api/v1/spool") - result.raise_for_status() - - # Verify - spools = result.json() - assert len(spools) == 2 - for spool in spools: - assert spool == added_spools_by_id[spool["id"]] - assert spool["archived"] is False - - # Execute - find all spools, including archived - result = httpx.get(f"{URL}/api/v1/spool?allow_archived=true") - result.raise_for_status() - - # Verify - spools = result.json() - assert len(spools) == 3 - for spool in spools: - assert spool == added_spools_by_id[spool["id"]] - - # Execute - find spools by filament name - result = httpx.get( - f"{URL}/api/v1/spool", - params={"filament_name": random_filament["name"]}, - ) - result.raise_for_status() - - # Verify - spools = result.json() - assert len(spools) == 2 - for spool in spools: - assert spool == added_spools_by_id[spool["id"]] - - # Execute - find spools by filament id - result = httpx.get( - f"{URL}/api/v1/spool", - params={"filament_id": random_filament["id"]}, - ) - result.raise_for_status() - - # Verify - spools = result.json() - assert len(spools) == 2 - for spool in spools: - assert spool == added_spools_by_id[spool["id"]] - - # Execute - find spools by filament material - result = httpx.get( - f"{URL}/api/v1/spool", - params={"filament_material": random_filament["material"]}, - ) - result.raise_for_status() - - # Verify - spools = result.json() - assert len(spools) == 2 - for spool in spools: - assert spool == added_spools_by_id[spool["id"]] - - # Execute - find spools by filament vendor name - result = httpx.get( - f"{URL}/api/v1/spool", - params={"vendor_name": random_filament["vendor"]["name"]}, - ) - result.raise_for_status() - - # Verify - spools = result.json() - assert len(spools) == 2 - for spool in spools: - assert spool == added_spools_by_id[spool["id"]] - - # Execute - find spools by filament vendor id - result = httpx.get( - f"{URL}/api/v1/spool", - params={"vendor_id": random_filament["vendor"]["id"]}, - ) - result.raise_for_status() - - # Verify - spools = result.json() - assert len(spools) == 2 - for spool in spools: - assert spool == added_spools_by_id[spool["id"]] - - # Execute - find spools by location - result = httpx.get( - f"{URL}/api/v1/spool", - params={"location": "The Pantry"}, - ) - result.raise_for_status() - - # Verify - spools = result.json() - assert len(spools) == 1 - assert spools[0] == added_spools_by_id[spool_1["id"]] - - # Execute - find spools by lot nr - result = httpx.get( - f"{URL}/api/v1/spool", - params={"lot_nr": "123456789"}, - ) - result.raise_for_status() - - # Verify - spools = result.json() - assert len(spools) == 1 - assert spools[0] == added_spools_by_id[spool_1["id"]] - - # Clean up - httpx.delete(f"{URL}/api/v1/spool/{spool_1['id']}").raise_for_status() - httpx.delete(f"{URL}/api/v1/spool/{spool_2['id']}").raise_for_status() - httpx.delete(f"{URL}/api/v1/spool/{spool_3['id']}").raise_for_status() - - -def test_delete_spool(random_filament: dict[str, Any]): - """Test deleting a spool from the database.""" - # Setup - result = httpx.post( - f"{URL}/api/v1/spool", - json={ - "filament_id": random_filament["id"], - "remaining_weight": 1000, - "location": "The Pantry", - "lot_nr": "123456789", - }, - ) - result.raise_for_status() - spool = result.json() - - # Execute - httpx.delete(f"{URL}/api/v1/spool/{spool['id']}").raise_for_status() - - # Verify - result = httpx.get(f"{URL}/api/v1/spool/{spool['id']}") - assert result.status_code == 404 - - -def test_delete_spool_not_found(): - """Test deleting a spool that does not exist.""" - # Execute - result = httpx.delete(f"{URL}/api/v1/spool/123456789") - - # Verify - assert result.status_code == 404 - message = result.json()["message"].lower() - assert "spool" in message - assert "id" in message - assert "123456789" in message - - -def test_update_spool(random_filament: dict[str, Any]): - """Test updating a spool in the database.""" - # Setup - result = httpx.post( - f"{URL}/api/v1/spool", - json={ - "filament_id": random_filament["id"], - "remaining_weight": 1000, - "location": "The Pantry", - "lot_nr": "123456789", - }, - ) - result.raise_for_status() - spool = result.json() - - # Execute - first_used = "2023-01-01T12:00:00+02:00" - last_used = "2023-01-02T12:00:00+02:00" - remaining_weight = 750 - location = "Living Room" - lot_nr = "987654321" - comment = "abcdefghåäö" - archived = True - result = httpx.patch( - f"{URL}/api/v1/spool/{spool['id']}", - json={ - "first_used": first_used, - "last_used": last_used, - "remaining_weight": remaining_weight, - "location": location, - "lot_nr": lot_nr, - "comment": comment, - "archived": archived, - }, - ) - result.raise_for_status() - - # Verify - used_weight = random_filament["weight"] - remaining_weight - used_length = length_from_weight( - weight=used_weight, - density=random_filament["density"], - diameter=random_filament["diameter"], - ) - remaining_length = length_from_weight( - weight=remaining_weight, - density=random_filament["density"], - diameter=random_filament["diameter"], - ) - - spool = result.json() - assert spool["first_used"] == "2023-01-01T10:00:00" - assert spool["last_used"] == "2023-01-02T10:00:00" - assert spool["remaining_weight"] == pytest.approx(remaining_weight) - assert spool["used_weight"] == pytest.approx(used_weight) - assert spool["remaining_length"] == pytest.approx(remaining_length) - assert spool["used_length"] == pytest.approx(used_length) - assert spool["location"] == location - assert spool["lot_nr"] == lot_nr - assert spool["comment"] == comment - assert spool["archived"] == archived - - # Clean up - httpx.delete(f"{URL}/api/v1/spool/{spool['id']}").raise_for_status() - - -def test_update_spool_both_used_and_remaining_weight(random_filament: dict[str, Any]): - """Test updating a spool in the database.""" - # Setup - result = httpx.post( - f"{URL}/api/v1/spool", - json={"filament_id": random_filament["id"]}, - ) - result.raise_for_status() - spool = result.json() - - # Execute - result = httpx.patch( - f"{URL}/api/v1/spool/{spool['id']}", - json={ - "remaining_weight": 750, - "used_weight": 250, - }, - ) - assert result.status_code == 400 # Cannot update both used and remaining weight - - # Clean up - httpx.delete(f"{URL}/api/v1/spool/{spool['id']}").raise_for_status() - - -def test_update_spool_not_found(random_filament: dict[str, Any]): - """Test updating a spool that does not exist.""" - # Execute - result = httpx.patch( - f"{URL}/api/v1/spool/123456789", - json={"filament_id": random_filament["id"]}, - ) - assert result.status_code == 404 - message = result.json()["message"].lower() - assert "spool" in message - assert "id" in message - assert "123456789" in message - - -@pytest.mark.parametrize("use_weight", [0, 0.05, -0.05, 1500]) # 1500 is big enough to use all filament -def test_use_spool_weight(random_filament: dict[str, Any], use_weight: float): - """Test using a spool in the database.""" - # Setup - filament_net_weight = random_filament["weight"] - start_weight = 1000 - result = httpx.post( - f"{URL}/api/v1/spool", - json={ - "filament_id": random_filament["id"], - "remaining_weight": start_weight, - }, - ) - result.raise_for_status() - spool = result.json() - - # Execute - result = httpx.put( - f"{URL}/api/v1/spool/{spool['id']}/use", - json={ - "use_weight": use_weight, - }, - ) - result.raise_for_status() - - # Verify - spool = result.json() - # remaining_weight should be clamped so it's never negative, but used_weight should not be clamped to the net weight - assert spool["used_weight"] == pytest.approx(max(use_weight, 0)) - assert spool["remaining_weight"] == pytest.approx(min(max(start_weight - use_weight, 0), filament_net_weight)) - - # Clean up - httpx.delete(f"{URL}/api/v1/spool/{spool['id']}").raise_for_status() - - -@pytest.mark.parametrize("use_length", [0, 10, -10, 500e3]) # 500e3 is big enough to use all the filament -def test_use_spool_length(random_filament: dict[str, Any], use_length: float): - """Test using a spool in the database.""" - # Setup - filament_net_weight = random_filament["weight"] - start_weight = 1000 - result = httpx.post( - f"{URL}/api/v1/spool", - json={ - "filament_id": random_filament["id"], - "remaining_weight": start_weight, - }, - ) - result.raise_for_status() - spool = result.json() - - # Execute - result = httpx.put( - f"{URL}/api/v1/spool/{spool['id']}/use", - json={ - "use_length": use_length, - }, - ) - result.raise_for_status() - - # Verify - spool = result.json() - use_weight = ( - random_filament["density"] * (use_length * 1e-1) * math.pi * ((random_filament["diameter"] * 1e-1 / 2) ** 2) - ) - # remaining_weight should be clamped so it's never negative, but used_weight should not be clamped to the net weight - assert spool["used_weight"] == pytest.approx(max(use_weight, 0)) - assert spool["remaining_weight"] == pytest.approx(min(max(start_weight - use_weight, 0), filament_net_weight)) - - # Clean up - httpx.delete(f"{URL}/api/v1/spool/{spool['id']}").raise_for_status() - - -def test_use_spool_weight_and_length(random_filament: dict[str, Any]): - """Test using a spool in the database.""" - # Setup - result = httpx.post( - f"{URL}/api/v1/spool", - json={"filament_id": random_filament["id"]}, - ) - result.raise_for_status() - spool = result.json() - - # Execute - result = httpx.put( - f"{URL}/api/v1/spool/{spool['id']}/use", - json={ - "use_weight": 0.05, - "use_length": 10, - }, - ) - assert result.status_code == 400 # Cannot use both weight and length - - # Clean up - httpx.delete(f"{URL}/api/v1/spool/{spool['id']}").raise_for_status() - - -def test_use_spool_not_found(): - """Test using a spool that does not exist.""" - # Execute - result = httpx.put( - f"{URL}/api/v1/spool/123456789/use", - json={"use_weight": 0.05}, - ) - assert result.status_code == 404 - message = result.json()["message"].lower() - assert "spool" in message - assert "id" in message - assert "123456789" in message - - -@pytest.mark.asyncio() -async def test_use_spool_concurrent(random_filament: dict[str, Any]): - """Test using a spool with many concurrent requests.""" - # Setup - start_weight = 1000 - result = httpx.post( # noqa: ASYNC100 - f"{URL}/api/v1/spool", - json={ - "filament_id": random_filament["id"], - "remaining_weight": start_weight, - }, - ) - result.raise_for_status() - spool = result.json() - - # Execute - requests = 100 - used_weight = 0.5 - async with httpx.AsyncClient() as client: - await asyncio.gather( - *( - client.put( - f"{URL}/api/v1/spool/{spool['id']}/use", - json={ - "use_weight": used_weight, - }, - timeout=60, - ) - for _ in range(requests) - ), - ) - - # Verify - result = httpx.get(f"{URL}/api/v1/spool/{spool['id']}") # noqa: ASYNC100 - result.raise_for_status() - spool = result.json() - assert spool["remaining_weight"] == pytest.approx(start_weight - (used_weight * requests)) - - # Clean up - httpx.delete(f"{URL}/api/v1/spool/{spool['id']}").raise_for_status() # noqa: ASYNC100 diff --git a/tests_integration/tests/test_vendor.py b/tests_integration/tests/test_vendor.py deleted file mode 100644 index 967f969..0000000 --- a/tests_integration/tests/test_vendor.py +++ /dev/null @@ -1,237 +0,0 @@ -"""Integration tests for the Vendor API endpoint.""" - -import httpx - -URL = "http://spoolman:8000" - - -def test_add_vendor(): - """Test adding a vendor to the database.""" - # Execute - name = "John" - comment = "abcdefghåäö" - result = httpx.post( - f"{URL}/api/v1/vendor", - json={"name": name, "comment": comment}, - ) - result.raise_for_status() - - # Verify - vendor = result.json() - assert vendor == { - "id": vendor["id"], - "registered": vendor["registered"], - "name": name, - "comment": comment, - } - - # Clean up - httpx.delete(f"{URL}/api/v1/vendor/{vendor['id']}").raise_for_status() - - -def test_add_vendor_required(): - """Test adding a vendor with only the required fields to the database.""" - # Execute - name = "John" - result = httpx.post( - f"{URL}/api/v1/vendor", - json={"name": name}, - ) - result.raise_for_status() - - # Verify - vendor = result.json() - assert vendor == { - "id": vendor["id"], - "registered": vendor["registered"], - "name": name, - } - - # Clean up - httpx.delete(f"{URL}/api/v1/vendor/{vendor['id']}").raise_for_status() - - -def test_get_vendor(): - """Test getting a vendor from the database.""" - # Setup - name = "John" - comment = "abcdefghåäö" - result = httpx.post( - f"{URL}/api/v1/vendor", - json={"name": name, "comment": comment}, - ) - result.raise_for_status() - added_vendor = result.json() - - # Execute - result = httpx.get( - f"{URL}/api/v1/vendor/{added_vendor['id']}", - ) - result.raise_for_status() - - # Verify - vendor = result.json() - assert vendor["name"] == name - assert vendor["comment"] == comment - assert vendor["id"] == added_vendor["id"] - assert vendor["registered"] == added_vendor["registered"] - - # Clean up - httpx.delete(f"{URL}/api/v1/vendor/{vendor['id']}").raise_for_status() - - -def test_get_vendor_not_found(): - """Test getting a vendor that does not exist.""" - # Execute - result = httpx.get(f"{URL}/api/v1/vendor/123456789") - - # Verify - assert result.status_code == 404 - message = result.json()["message"].lower() - assert "vendor" in message - assert "id" in message - assert "123456789" in message - - -def test_find_vendors(): - """Test finding vendors from the database.""" - # Setup - name_1 = "John" - comment_1 = "abcdefghåäö" - result = httpx.post( - f"{URL}/api/v1/vendor", - json={"name": name_1, "comment": comment_1}, - ) - result.raise_for_status() - vendor_1 = result.json() - - name_2 = "Stan" - comment_2 = "gfdadfg" - result = httpx.post( - f"{URL}/api/v1/vendor", - json={"name": name_2, "comment": comment_2}, - ) - result.raise_for_status() - vendor_2 = result.json() - - added_vendors_by_id = { - vendor_1["id"]: vendor_1, - vendor_2["id"]: vendor_2, - } - - # Execute - Find all vendors - result = httpx.get( - f"{URL}/api/v1/vendor", - ) - result.raise_for_status() - - # Verify - vendors = result.json() - assert len(vendors) == 2 - - for vendor in vendors: - assert vendor == added_vendors_by_id[vendor["id"]] - - # Execute - Find a specific vendor - result = httpx.get( - f"{URL}/api/v1/vendor", - params={"name": name_1}, - ) - result.raise_for_status() - - # Verify - vendors = result.json() - assert len(vendors) == 1 - - vendor = vendors[0] - - assert vendor["name"] == name_1 - assert vendor["comment"] == comment_1 - assert vendor["id"] == vendor_1["id"] - assert vendor["registered"] == vendor_1["registered"] - - # Clean up - httpx.delete(f"{URL}/api/v1/vendor/{vendor_1['id']}").raise_for_status() - httpx.delete(f"{URL}/api/v1/vendor/{vendor_2['id']}").raise_for_status() - - -def test_delete_vendor(): - """Test deleting a vendor from the database.""" - # Setup - name = "John" - comment = "abcdefghåäö" - result = httpx.post( - f"{URL}/api/v1/vendor", - json={"name": name, "comment": comment}, - ) - result.raise_for_status() - added_vendor = result.json() - - # Execute - httpx.delete( - f"{URL}/api/v1/vendor/{added_vendor['id']}", - ).raise_for_status() - - # Verify - result = httpx.get( - f"{URL}/api/v1/vendor/{added_vendor['id']}", - ) - assert result.status_code == 404 - - -def test_delete_vendor_not_found(): - """Test deleting a vendor that does not exist.""" - # Execute - result = httpx.delete(f"{URL}/api/v1/vendor/123456789") - - # Verify - assert result.status_code == 404 - message = result.json()["message"].lower() - assert "vendor" in message - assert "id" in message - assert "123456789" in message - - -def test_update_vendor(): - """Test update a vendor in the database.""" - # Setup - name = "John" - comment = "abcdefghåäö" - result = httpx.post( - f"{URL}/api/v1/vendor", - json={"name": name, "comment": comment}, - ) - result.raise_for_status() - added_vendor = result.json() - - # Execute - new_name = "Stan" - new_comment = "gfdadfg" - result = httpx.patch( - f"{URL}/api/v1/vendor/{added_vendor['id']}", - json={"name": new_name, "comment": new_comment}, - ) - result.raise_for_status() - - # Verify - vendor = result.json() - assert vendor["name"] == new_name - assert vendor["comment"] == new_comment - assert vendor["id"] == added_vendor["id"] - assert vendor["registered"] == added_vendor["registered"] - - # Clean up - httpx.delete(f"{URL}/api/v1/vendor/{vendor['id']}").raise_for_status() - - -def test_update_vendor_not_found(): - """Test updating a vendor that does not exist.""" - # Execute - result = httpx.patch(f"{URL}/api/v1/vendor/123456789", json={"name": "John"}) - - # Verify - assert result.status_code == 404 - message = result.json()["message"].lower() - assert "vendor" in message - assert "id" in message - assert "123456789" in message diff --git a/tests_integration/tests/vendor/__init__.py b/tests_integration/tests/vendor/__init__.py new file mode 100644 index 0000000..f374113 --- /dev/null +++ b/tests_integration/tests/vendor/__init__.py @@ -0,0 +1 @@ +"""Tests for the vendor API.""" diff --git a/tests_integration/tests/vendor/test_add.py b/tests_integration/tests/vendor/test_add.py new file mode 100644 index 0000000..d82ac97 --- /dev/null +++ b/tests_integration/tests/vendor/test_add.py @@ -0,0 +1,51 @@ +"""Integration tests for the Vendor API endpoint.""" + +import httpx + +URL = "http://spoolman:8000" + + +def test_add_vendor(): + """Test adding a vendor to the database.""" + # Execute + name = "John" + comment = "abcdefghåäö" + result = httpx.post( + f"{URL}/api/v1/vendor", + json={"name": name, "comment": comment}, + ) + result.raise_for_status() + + # Verify + vendor = result.json() + assert vendor == { + "id": vendor["id"], + "registered": vendor["registered"], + "name": name, + "comment": comment, + } + + # Clean up + httpx.delete(f"{URL}/api/v1/vendor/{vendor['id']}").raise_for_status() + + +def test_add_vendor_required(): + """Test adding a vendor with only the required fields to the database.""" + # Execute + name = "John" + result = httpx.post( + f"{URL}/api/v1/vendor", + json={"name": name}, + ) + result.raise_for_status() + + # Verify + vendor = result.json() + assert vendor == { + "id": vendor["id"], + "registered": vendor["registered"], + "name": name, + } + + # Clean up + httpx.delete(f"{URL}/api/v1/vendor/{vendor['id']}").raise_for_status() diff --git a/tests_integration/tests/vendor/test_delete.py b/tests_integration/tests/vendor/test_delete.py new file mode 100644 index 0000000..f9d932b --- /dev/null +++ b/tests_integration/tests/vendor/test_delete.py @@ -0,0 +1,42 @@ +"""Integration tests for the Vendor API endpoint.""" + +import httpx + +URL = "http://spoolman:8000" + + +def test_delete_vendor(): + """Test deleting a vendor from the database.""" + # Setup + name = "John" + comment = "abcdefghåäö" + result = httpx.post( + f"{URL}/api/v1/vendor", + json={"name": name, "comment": comment}, + ) + result.raise_for_status() + added_vendor = result.json() + + # Execute + httpx.delete( + f"{URL}/api/v1/vendor/{added_vendor['id']}", + ).raise_for_status() + + # Verify + result = httpx.get( + f"{URL}/api/v1/vendor/{added_vendor['id']}", + ) + assert result.status_code == 404 + + +def test_delete_vendor_not_found(): + """Test deleting a vendor that does not exist.""" + # Execute + result = httpx.delete(f"{URL}/api/v1/vendor/123456789") + + # Verify + assert result.status_code == 404 + message = result.json()["message"].lower() + assert "vendor" in message + assert "id" in message + assert "123456789" in message diff --git a/tests_integration/tests/vendor/test_find.py b/tests_integration/tests/vendor/test_find.py new file mode 100644 index 0000000..e8aac2e --- /dev/null +++ b/tests_integration/tests/vendor/test_find.py @@ -0,0 +1,67 @@ +"""Integration tests for the Vendor API endpoint.""" + +import httpx + +URL = "http://spoolman:8000" + + +def test_find_vendors(): + """Test finding vendors from the database.""" + # Setup + name_1 = "John" + comment_1 = "abcdefghåäö" + result = httpx.post( + f"{URL}/api/v1/vendor", + json={"name": name_1, "comment": comment_1}, + ) + result.raise_for_status() + vendor_1 = result.json() + + name_2 = "Stan" + comment_2 = "gfdadfg" + result = httpx.post( + f"{URL}/api/v1/vendor", + json={"name": name_2, "comment": comment_2}, + ) + result.raise_for_status() + vendor_2 = result.json() + + added_vendors_by_id = { + vendor_1["id"]: vendor_1, + vendor_2["id"]: vendor_2, + } + + # Execute - Find all vendors + result = httpx.get( + f"{URL}/api/v1/vendor", + ) + result.raise_for_status() + + # Verify + vendors = result.json() + assert len(vendors) == 2 + + for vendor in vendors: + assert vendor == added_vendors_by_id[vendor["id"]] + + # Execute - Find a specific vendor + result = httpx.get( + f"{URL}/api/v1/vendor", + params={"name": name_1}, + ) + result.raise_for_status() + + # Verify + vendors = result.json() + assert len(vendors) == 1 + + vendor = vendors[0] + + assert vendor["name"] == name_1 + assert vendor["comment"] == comment_1 + assert vendor["id"] == vendor_1["id"] + assert vendor["registered"] == vendor_1["registered"] + + # Clean up + httpx.delete(f"{URL}/api/v1/vendor/{vendor_1['id']}").raise_for_status() + httpx.delete(f"{URL}/api/v1/vendor/{vendor_2['id']}").raise_for_status() diff --git a/tests_integration/tests/vendor/test_get.py b/tests_integration/tests/vendor/test_get.py new file mode 100644 index 0000000..eeab3f3 --- /dev/null +++ b/tests_integration/tests/vendor/test_get.py @@ -0,0 +1,47 @@ +"""Integration tests for the Vendor API endpoint.""" + +import httpx + +URL = "http://spoolman:8000" + + +def test_get_vendor(): + """Test getting a vendor from the database.""" + # Setup + name = "John" + comment = "abcdefghåäö" + result = httpx.post( + f"{URL}/api/v1/vendor", + json={"name": name, "comment": comment}, + ) + result.raise_for_status() + added_vendor = result.json() + + # Execute + result = httpx.get( + f"{URL}/api/v1/vendor/{added_vendor['id']}", + ) + result.raise_for_status() + + # Verify + vendor = result.json() + assert vendor["name"] == name + assert vendor["comment"] == comment + assert vendor["id"] == added_vendor["id"] + assert vendor["registered"] == added_vendor["registered"] + + # Clean up + httpx.delete(f"{URL}/api/v1/vendor/{vendor['id']}").raise_for_status() + + +def test_get_vendor_not_found(): + """Test getting a vendor that does not exist.""" + # Execute + result = httpx.get(f"{URL}/api/v1/vendor/123456789") + + # Verify + assert result.status_code == 404 + message = result.json()["message"].lower() + assert "vendor" in message + assert "id" in message + assert "123456789" in message diff --git a/tests_integration/tests/vendor/test_update.py b/tests_integration/tests/vendor/test_update.py new file mode 100644 index 0000000..dce3e74 --- /dev/null +++ b/tests_integration/tests/vendor/test_update.py @@ -0,0 +1,50 @@ +"""Integration tests for the Vendor API endpoint.""" + +import httpx + +URL = "http://spoolman:8000" + + +def test_update_vendor(): + """Test update a vendor in the database.""" + # Setup + name = "John" + comment = "abcdefghåäö" + result = httpx.post( + f"{URL}/api/v1/vendor", + json={"name": name, "comment": comment}, + ) + result.raise_for_status() + added_vendor = result.json() + + # Execute + new_name = "Stan" + new_comment = "gfdadfg" + result = httpx.patch( + f"{URL}/api/v1/vendor/{added_vendor['id']}", + json={"name": new_name, "comment": new_comment}, + ) + result.raise_for_status() + + # Verify + vendor = result.json() + assert vendor["name"] == new_name + assert vendor["comment"] == new_comment + assert vendor["id"] == added_vendor["id"] + assert vendor["registered"] == added_vendor["registered"] + + # Clean up + httpx.delete(f"{URL}/api/v1/vendor/{vendor['id']}").raise_for_status() + + +def test_update_vendor_not_found(): + """Test updating a vendor that does not exist.""" + # Execute + result = httpx.patch(f"{URL}/api/v1/vendor/123456789", json={"name": "John"}) + + # Verify + assert result.status_code == 404 + message = result.json()["message"].lower() + assert "vendor" in message + assert "id" in message + assert "123456789" in message