API find nested filters now specified using period
Previously you used underscore, like vendor_name. This made fields like filament_article_number have ambiguous underscores.
This commit is contained in:
@@ -115,12 +115,28 @@ class FilamentUpdateParameters(FilamentParameters):
|
|||||||
async def find(
|
async def find(
|
||||||
*,
|
*,
|
||||||
db: Annotated[AsyncSession, Depends(get_db_session)],
|
db: Annotated[AsyncSession, Depends(get_db_session)],
|
||||||
|
vendor_name_old: Optional[str] = Query(
|
||||||
|
alias="vendor_name",
|
||||||
|
default=None,
|
||||||
|
title="Vendor Name",
|
||||||
|
description="Partial case-insensitive search term for the filament vendor name.",
|
||||||
|
deprecated=True,
|
||||||
|
),
|
||||||
|
vendor_id_old: Optional[int] = Query(
|
||||||
|
alias="vendor_id",
|
||||||
|
default=None,
|
||||||
|
title="Vendor ID",
|
||||||
|
description="Match an exact vendor ID.",
|
||||||
|
deprecated=True,
|
||||||
|
),
|
||||||
vendor_name: Optional[str] = Query(
|
vendor_name: Optional[str] = Query(
|
||||||
|
alias="vendor.name",
|
||||||
default=None,
|
default=None,
|
||||||
title="Vendor Name",
|
title="Vendor Name",
|
||||||
description="Partial case-insensitive search term for the filament vendor name.",
|
description="Partial case-insensitive search term for the filament vendor name.",
|
||||||
),
|
),
|
||||||
vendor_id: Optional[int] = Query(
|
vendor_id: Optional[int] = Query(
|
||||||
|
alias="vendor.id",
|
||||||
default=None,
|
default=None,
|
||||||
title="Vendor ID",
|
title="Vendor ID",
|
||||||
description="Match an exact vendor ID.",
|
description="Match an exact vendor ID.",
|
||||||
@@ -167,8 +183,8 @@ async def find(
|
|||||||
|
|
||||||
db_items, total_count = await filament.find(
|
db_items, total_count = await filament.find(
|
||||||
db=db,
|
db=db,
|
||||||
vendor_name=vendor_name,
|
vendor_name=vendor_name if vendor_name is not None else vendor_name_old,
|
||||||
vendor_id=vendor_id,
|
vendor_id=vendor_id if vendor_id is not None else vendor_id_old,
|
||||||
name=name,
|
name=name,
|
||||||
material=material,
|
material=material,
|
||||||
article_number=article_number,
|
article_number=article_number,
|
||||||
|
|||||||
@@ -73,27 +73,67 @@ class SpoolUseParameters(BaseModel):
|
|||||||
async def find(
|
async def find(
|
||||||
*,
|
*,
|
||||||
db: Annotated[AsyncSession, Depends(get_db_session)],
|
db: Annotated[AsyncSession, Depends(get_db_session)],
|
||||||
|
filament_name_old: Optional[str] = Query(
|
||||||
|
alias="filament_name",
|
||||||
|
default=None,
|
||||||
|
title="Filament Name",
|
||||||
|
description="Partial case-insensitive search term for the filament name.",
|
||||||
|
deprecated=True,
|
||||||
|
),
|
||||||
|
filament_id_old: Optional[int] = Query(
|
||||||
|
alias="filament_id",
|
||||||
|
default=None,
|
||||||
|
title="Filament ID",
|
||||||
|
description="Match an exact filament ID.",
|
||||||
|
deprecated=True,
|
||||||
|
),
|
||||||
|
filament_material_old: Optional[str] = Query(
|
||||||
|
alias="filament_material",
|
||||||
|
default=None,
|
||||||
|
title="Filament Material",
|
||||||
|
description="Partial case-insensitive search term for the filament material.",
|
||||||
|
deprecated=True,
|
||||||
|
),
|
||||||
|
vendor_name_old: Optional[str] = Query(
|
||||||
|
alias="vendor_name",
|
||||||
|
default=None,
|
||||||
|
title="Vendor Name",
|
||||||
|
description="Partial case-insensitive search term for the filament vendor name.",
|
||||||
|
deprecated=True,
|
||||||
|
),
|
||||||
|
vendor_id_old: Optional[int] = Query(
|
||||||
|
alias="vendor_id",
|
||||||
|
default=None,
|
||||||
|
title="Vendor ID",
|
||||||
|
description="Match an exact vendor ID.",
|
||||||
|
deprecated=True,
|
||||||
|
),
|
||||||
filament_name: Optional[str] = Query(
|
filament_name: Optional[str] = Query(
|
||||||
|
alias="filament.name",
|
||||||
default=None,
|
default=None,
|
||||||
title="Filament Name",
|
title="Filament Name",
|
||||||
description="Partial case-insensitive search term for the filament name.",
|
description="Partial case-insensitive search term for the filament name.",
|
||||||
),
|
),
|
||||||
filament_id: Optional[int] = Query(
|
filament_id: Optional[int] = Query(
|
||||||
|
alias="filament.id",
|
||||||
default=None,
|
default=None,
|
||||||
title="Filament ID",
|
title="Filament ID",
|
||||||
description="Match an exact filament ID.",
|
description="Match an exact filament ID.",
|
||||||
),
|
),
|
||||||
filament_material: Optional[str] = Query(
|
filament_material: Optional[str] = Query(
|
||||||
|
alias="filament.material",
|
||||||
default=None,
|
default=None,
|
||||||
title="Filament Material",
|
title="Filament Material",
|
||||||
description="Partial case-insensitive search term for the filament material.",
|
description="Partial case-insensitive search term for the filament material.",
|
||||||
),
|
),
|
||||||
vendor_name: Optional[str] = Query(
|
vendor_name: Optional[str] = Query(
|
||||||
|
alias="vendor.name",
|
||||||
default=None,
|
default=None,
|
||||||
title="Vendor Name",
|
title="Vendor Name",
|
||||||
description="Partial case-insensitive search term for the filament vendor name.",
|
description="Partial case-insensitive search term for the filament vendor name.",
|
||||||
),
|
),
|
||||||
vendor_id: Optional[int] = Query(
|
vendor_id: Optional[int] = Query(
|
||||||
|
alias="vendor.id",
|
||||||
default=None,
|
default=None,
|
||||||
title="Vendor ID",
|
title="Vendor ID",
|
||||||
description="Match an exact vendor ID.",
|
description="Match an exact vendor ID.",
|
||||||
@@ -119,7 +159,7 @@ async def find(
|
|||||||
description=(
|
description=(
|
||||||
'Sort the results by the given field. Should be a comma-separate string with "field:direction" items.'
|
'Sort the results by the given field. Should be a comma-separate string with "field:direction" items.'
|
||||||
),
|
),
|
||||||
example="filament.name:asc,location:desc",
|
example="filament.name:asc,vendor.id:asc,location:desc",
|
||||||
),
|
),
|
||||||
limit: Optional[int] = Query(
|
limit: Optional[int] = Query(
|
||||||
default=None,
|
default=None,
|
||||||
@@ -140,11 +180,11 @@ async def find(
|
|||||||
|
|
||||||
db_items, total_count = await spool.find(
|
db_items, total_count = await spool.find(
|
||||||
db=db,
|
db=db,
|
||||||
filament_name=filament_name,
|
filament_name=filament_name if filament_name is not None else filament_name_old,
|
||||||
filament_id=filament_id,
|
filament_id=filament_id if filament_id is not None else filament_id_old,
|
||||||
filament_material=filament_material,
|
filament_material=filament_material if filament_material is not None else filament_material_old,
|
||||||
vendor_name=vendor_name,
|
vendor_name=vendor_name if vendor_name is not None else vendor_name_old,
|
||||||
vendor_id=vendor_id,
|
vendor_id=vendor_id if vendor_id is not None else vendor_id_old,
|
||||||
location=location,
|
location=location,
|
||||||
lot_nr=lot_nr,
|
lot_nr=lot_nr,
|
||||||
allow_archived=allow_archived,
|
allow_archived=allow_archived,
|
||||||
|
|||||||
@@ -1,15 +1,24 @@
|
|||||||
"""Integration tests for the Filament API endpoint."""
|
"""Integration tests for the Filament API endpoint."""
|
||||||
|
|
||||||
|
from collections.abc import Iterable
|
||||||
|
from dataclasses import dataclass
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
import httpx
|
import httpx
|
||||||
|
import pytest
|
||||||
|
|
||||||
URL = "http://spoolman:8000"
|
URL = "http://spoolman:8000"
|
||||||
|
|
||||||
|
|
||||||
def test_find_filaments(random_vendor: dict[str, Any]):
|
@dataclass
|
||||||
"""Test finding filaments from the database."""
|
class Fixture:
|
||||||
# Setup
|
filaments: list[dict[str, Any]]
|
||||||
|
filaments_by_id: dict[str, dict[str, Any]]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture()
|
||||||
|
def filaments(random_vendor: dict[str, Any]) -> Iterable[Fixture]:
|
||||||
|
"""Add some filaments to the database."""
|
||||||
result = httpx.post(
|
result = httpx.post(
|
||||||
f"{URL}/api/v1/filament",
|
f"{URL}/api/v1/filament",
|
||||||
json={
|
json={
|
||||||
@@ -46,24 +55,57 @@ def test_find_filaments(random_vendor: dict[str, Any]):
|
|||||||
result.raise_for_status()
|
result.raise_for_status()
|
||||||
filament_2 = result.json()
|
filament_2 = result.json()
|
||||||
|
|
||||||
|
result = httpx.post(
|
||||||
|
f"{URL}/api/v1/filament",
|
||||||
|
json={
|
||||||
|
"name": "Filament Y",
|
||||||
|
"material": "PETG",
|
||||||
|
"price": 200,
|
||||||
|
"density": 1.25,
|
||||||
|
"diameter": 1.75,
|
||||||
|
"weight": 1000,
|
||||||
|
"spool_weight": 250,
|
||||||
|
"article_number": "abc",
|
||||||
|
"comment": "abcdefghåäö",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
result.raise_for_status()
|
||||||
|
filament_3 = result.json()
|
||||||
|
|
||||||
added_filaments_by_id = {
|
added_filaments_by_id = {
|
||||||
filament_1["id"]: filament_1,
|
filament_1["id"]: filament_1,
|
||||||
filament_2["id"]: filament_2,
|
filament_2["id"]: filament_2,
|
||||||
|
filament_3["id"]: filament_3,
|
||||||
}
|
}
|
||||||
|
|
||||||
# Execute - find all filaments
|
yield Fixture(
|
||||||
|
filaments=[filament_1, filament_2, filament_3],
|
||||||
|
filaments_by_id=added_filaments_by_id,
|
||||||
|
)
|
||||||
|
|
||||||
|
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()
|
||||||
|
httpx.delete(f"{URL}/api/v1/filament/{filament_3['id']}").raise_for_status()
|
||||||
|
|
||||||
|
|
||||||
|
def test_find_all_filaments(filaments: Fixture):
|
||||||
|
"""Test finding filaments from the database."""
|
||||||
|
# Execute
|
||||||
result = httpx.get(
|
result = httpx.get(
|
||||||
f"{URL}/api/v1/filament",
|
f"{URL}/api/v1/filament",
|
||||||
)
|
)
|
||||||
result.raise_for_status()
|
result.raise_for_status()
|
||||||
|
|
||||||
# Verify
|
# Verify
|
||||||
filaments = result.json()
|
filaments_result = result.json()
|
||||||
assert len(filaments) == 2
|
assert len(filaments_result) == 3
|
||||||
for filament in filaments:
|
for filament in filaments_result:
|
||||||
assert filament == added_filaments_by_id[filament["id"]]
|
assert filament == filaments.filaments_by_id[filament["id"]]
|
||||||
|
|
||||||
# Execute - find filaments by name
|
|
||||||
|
def test_find_filaments_by_name(filaments: Fixture):
|
||||||
|
"""Test finding filaments from the database."""
|
||||||
|
# Execute
|
||||||
result = httpx.get(
|
result = httpx.get(
|
||||||
f"{URL}/api/v1/filament",
|
f"{URL}/api/v1/filament",
|
||||||
params={"name": "Filament X"},
|
params={"name": "Filament X"},
|
||||||
@@ -71,11 +113,14 @@ def test_find_filaments(random_vendor: dict[str, Any]):
|
|||||||
result.raise_for_status()
|
result.raise_for_status()
|
||||||
|
|
||||||
# Verify
|
# Verify
|
||||||
filaments = result.json()
|
filaments_result = result.json()
|
||||||
assert len(filaments) == 1
|
assert len(filaments_result) == 1
|
||||||
assert filaments[0] == added_filaments_by_id[filament_1["id"]]
|
assert filaments_result[0] == filaments.filaments[0]
|
||||||
|
|
||||||
# Execute - find filaments by material
|
|
||||||
|
def test_find_filaments_by_material(filaments: Fixture):
|
||||||
|
"""Test finding filaments from the database."""
|
||||||
|
# Execute
|
||||||
result = httpx.get(
|
result = httpx.get(
|
||||||
f"{URL}/api/v1/filament",
|
f"{URL}/api/v1/filament",
|
||||||
params={"material": "abs"},
|
params={"material": "abs"},
|
||||||
@@ -83,37 +128,48 @@ def test_find_filaments(random_vendor: dict[str, Any]):
|
|||||||
result.raise_for_status()
|
result.raise_for_status()
|
||||||
|
|
||||||
# Verify
|
# Verify
|
||||||
filaments = result.json()
|
filaments_result = result.json()
|
||||||
assert len(filaments) == 1
|
assert len(filaments_result) == 1
|
||||||
assert filaments[0] == added_filaments_by_id[filament_2["id"]]
|
assert filaments_result[0] == filaments.filaments[1]
|
||||||
|
|
||||||
# Execute - find filaments by vendor id
|
|
||||||
|
@pytest.mark.parametrize("field_name", ["vendor_id", "vendor.id"])
|
||||||
|
def test_find_filaments_by_vendor_id(filaments: Fixture, field_name: str):
|
||||||
|
"""Test finding filaments from the database."""
|
||||||
|
# Execute
|
||||||
result = httpx.get(
|
result = httpx.get(
|
||||||
f"{URL}/api/v1/filament",
|
f"{URL}/api/v1/filament",
|
||||||
params={"vendor_id": random_vendor["id"]},
|
params={field_name: filaments.filaments[0]["vendor"]["id"]},
|
||||||
)
|
)
|
||||||
result.raise_for_status()
|
result.raise_for_status()
|
||||||
|
|
||||||
# Verify
|
# Verify
|
||||||
filaments = result.json()
|
filaments_result = result.json()
|
||||||
assert len(filaments) == 2
|
assert len(filaments_result) == 2
|
||||||
for filament in filaments:
|
for filament in filaments_result:
|
||||||
assert filament == added_filaments_by_id[filament["id"]]
|
assert filament == filaments.filaments_by_id[filament["id"]]
|
||||||
|
|
||||||
# Execute - find filaments by vendor name
|
|
||||||
|
@pytest.mark.parametrize("field_name", ["vendor_name", "vendor.name"])
|
||||||
|
def test_find_filaments_by_vendor_name(filaments: Fixture, field_name: str):
|
||||||
|
"""Test finding filaments from the database."""
|
||||||
|
# Execute
|
||||||
result = httpx.get(
|
result = httpx.get(
|
||||||
f"{URL}/api/v1/filament",
|
f"{URL}/api/v1/filament",
|
||||||
params={"vendor_name": random_vendor["name"]},
|
params={field_name: filaments.filaments[0]["vendor"]["name"]},
|
||||||
)
|
)
|
||||||
result.raise_for_status()
|
result.raise_for_status()
|
||||||
|
|
||||||
# Verify
|
# Verify
|
||||||
filaments = result.json()
|
filaments_result = result.json()
|
||||||
assert len(filaments) == 2
|
assert len(filaments_result) == 2
|
||||||
for filament in filaments:
|
for filament in filaments_result:
|
||||||
assert filament == added_filaments_by_id[filament["id"]]
|
assert filament == filaments.filaments_by_id[filament["id"]]
|
||||||
|
|
||||||
# Execute - find filaments by article number
|
|
||||||
|
def test_find_filaments_by_article_number(filaments: Fixture):
|
||||||
|
"""Test finding filaments from the database."""
|
||||||
|
# Execute
|
||||||
result = httpx.get(
|
result = httpx.get(
|
||||||
f"{URL}/api/v1/filament",
|
f"{URL}/api/v1/filament",
|
||||||
params={"article_number": "321"},
|
params={"article_number": "321"},
|
||||||
@@ -121,10 +177,6 @@ def test_find_filaments(random_vendor: dict[str, Any]):
|
|||||||
result.raise_for_status()
|
result.raise_for_status()
|
||||||
|
|
||||||
# Verify
|
# Verify
|
||||||
filaments = result.json()
|
filaments_result = result.json()
|
||||||
assert len(filaments) == 1
|
assert len(filaments_result) == 1
|
||||||
assert filaments[0] == added_filaments_by_id[filament_2["id"]]
|
assert filaments_result[0] == filaments.filaments[1]
|
||||||
|
|
||||||
# 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()
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
"""Integration tests for the Spool API endpoint."""
|
"""Integration tests for the Spool API endpoint."""
|
||||||
|
|
||||||
from collections.abc import Iterator
|
from collections.abc import Iterable
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@ class Fixture:
|
|||||||
|
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
def spools(random_filament: dict[str, Any]) -> Iterator[Fixture]:
|
def spools(random_filament: dict[str, Any]) -> Iterable[Fixture]:
|
||||||
"""Add some spools to the database."""
|
"""Add some spools to the database."""
|
||||||
result = httpx.post(
|
result = httpx.post(
|
||||||
f"{URL}/api/v1/spool",
|
f"{URL}/api/v1/spool",
|
||||||
@@ -99,12 +99,13 @@ def test_find_all_spools_including_archived(spools: Fixture):
|
|||||||
assert spool == spools.spools_by_id[spool["id"]]
|
assert spool == spools.spools_by_id[spool["id"]]
|
||||||
|
|
||||||
|
|
||||||
def test_find_spools_by_filament_name(spools: Fixture):
|
@pytest.mark.parametrize("field_name", ["filament_name", "filament.name"])
|
||||||
|
def test_find_spools_by_filament_name(spools: Fixture, field_name: str):
|
||||||
"""Test finding spools by filament name."""
|
"""Test finding spools by filament name."""
|
||||||
# Execute
|
# Execute
|
||||||
result = httpx.get(
|
result = httpx.get(
|
||||||
f"{URL}/api/v1/spool",
|
f"{URL}/api/v1/spool",
|
||||||
params={"filament_name": spools.filament["name"]},
|
params={field_name: spools.filament["name"]},
|
||||||
)
|
)
|
||||||
result.raise_for_status()
|
result.raise_for_status()
|
||||||
|
|
||||||
@@ -115,12 +116,13 @@ def test_find_spools_by_filament_name(spools: Fixture):
|
|||||||
assert spool == spools.spools_by_id[spool["id"]]
|
assert spool == spools.spools_by_id[spool["id"]]
|
||||||
|
|
||||||
|
|
||||||
def test_find_spools_by_filament_id(spools: Fixture):
|
@pytest.mark.parametrize("field_name", ["filament_id", "filament.id"])
|
||||||
|
def test_find_spools_by_filament_id(spools: Fixture, field_name: str):
|
||||||
"""Test finding spools by filament id."""
|
"""Test finding spools by filament id."""
|
||||||
# Execute
|
# Execute
|
||||||
result = httpx.get(
|
result = httpx.get(
|
||||||
f"{URL}/api/v1/spool",
|
f"{URL}/api/v1/spool",
|
||||||
params={"filament_id": spools.filament["id"]},
|
params={field_name: spools.filament["id"]},
|
||||||
)
|
)
|
||||||
result.raise_for_status()
|
result.raise_for_status()
|
||||||
|
|
||||||
@@ -131,12 +133,13 @@ def test_find_spools_by_filament_id(spools: Fixture):
|
|||||||
assert spool == spools.spools_by_id[spool["id"]]
|
assert spool == spools.spools_by_id[spool["id"]]
|
||||||
|
|
||||||
|
|
||||||
def test_find_spools_by_filament_material(spools: Fixture):
|
@pytest.mark.parametrize("field_name", ["filament_material", "filament.material"])
|
||||||
|
def test_find_spools_by_filament_material(spools: Fixture, field_name: str):
|
||||||
"""Test finding spools by filament material."""
|
"""Test finding spools by filament material."""
|
||||||
# Execute
|
# Execute
|
||||||
result = httpx.get(
|
result = httpx.get(
|
||||||
f"{URL}/api/v1/spool",
|
f"{URL}/api/v1/spool",
|
||||||
params={"filament_material": spools.filament["material"]},
|
params={field_name: spools.filament["material"]},
|
||||||
)
|
)
|
||||||
result.raise_for_status()
|
result.raise_for_status()
|
||||||
|
|
||||||
@@ -147,12 +150,13 @@ def test_find_spools_by_filament_material(spools: Fixture):
|
|||||||
assert spool == spools.spools_by_id[spool["id"]]
|
assert spool == spools.spools_by_id[spool["id"]]
|
||||||
|
|
||||||
|
|
||||||
def test_find_spools_by_filament_vendor_name(spools: Fixture):
|
@pytest.mark.parametrize("field_name", ["vendor_name", "vendor.name"])
|
||||||
|
def test_find_spools_by_filament_vendor_name(spools: Fixture, field_name: str):
|
||||||
"""Test finding spools by filament vendor name."""
|
"""Test finding spools by filament vendor name."""
|
||||||
# Execute
|
# Execute
|
||||||
result = httpx.get(
|
result = httpx.get(
|
||||||
f"{URL}/api/v1/spool",
|
f"{URL}/api/v1/spool",
|
||||||
params={"vendor_name": spools.filament["vendor"]["name"]},
|
params={field_name: spools.filament["vendor"]["name"]},
|
||||||
)
|
)
|
||||||
result.raise_for_status()
|
result.raise_for_status()
|
||||||
|
|
||||||
@@ -163,12 +167,13 @@ def test_find_spools_by_filament_vendor_name(spools: Fixture):
|
|||||||
assert spool == spools.spools_by_id[spool["id"]]
|
assert spool == spools.spools_by_id[spool["id"]]
|
||||||
|
|
||||||
|
|
||||||
def test_find_spools_by_filament_vendor_id(spools: Fixture):
|
@pytest.mark.parametrize("field_name", ["vendor_id", "vendor.id"])
|
||||||
|
def test_find_spools_by_filament_vendor_id(spools: Fixture, field_name: str):
|
||||||
"""Test finding spools by filament vendor id."""
|
"""Test finding spools by filament vendor id."""
|
||||||
# Execute
|
# Execute
|
||||||
result = httpx.get(
|
result = httpx.get(
|
||||||
f"{URL}/api/v1/spool",
|
f"{URL}/api/v1/spool",
|
||||||
params={"vendor_id": spools.filament["vendor"]["id"]},
|
params={field_name: spools.filament["vendor"]["id"]},
|
||||||
)
|
)
|
||||||
result.raise_for_status()
|
result.raise_for_status()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user