Adding filters and controls for scopes
This commit is contained in:
1 parent
3febc15a8f
commit
2587ccbceb
6 files changed
+292
-94
No files matched your search
@@ -4,6 +4,7 @@ from app.models.augmented_part import AugmentedPart
|
||||
from app.models.fit import Fit, FitLabel
|
||||
from app.models.part_type import PartType
|
||||
from app.models.scope_info import ScopeInfo
|
||||
from app.models.sub_part_type import SubPartType
|
||||
from app.services import scope_guide
|
||||
|
||||
|
||||
@@ -14,15 +15,24 @@ async def _seed_guide_data(db):
|
||||
db.add_all([scope_t, cover_t, ard_t])
|
||||
await db.flush()
|
||||
|
||||
def part(desc, type_id):
|
||||
rifle = SubPartType(name="Riflescope", part_type_id=scope_t.id)
|
||||
reddot = SubPartType(name="Red Dot", part_type_id=scope_t.id)
|
||||
db.add_all([rifle, reddot])
|
||||
await db.flush()
|
||||
|
||||
def part(desc, type_id, manufacturer_id=1, sub_part_type_id=None):
|
||||
p = AugmentedPart(
|
||||
description=desc, colour_id=1, manufacturer_id=1, part_type_id=type_id
|
||||
description=desc,
|
||||
colour_id=1,
|
||||
manufacturer_id=manufacturer_id,
|
||||
part_type_id=type_id,
|
||||
sub_part_type_id=sub_part_type_id,
|
||||
)
|
||||
db.add(p)
|
||||
return p
|
||||
|
||||
s1 = part("Alpha 3-18x50", scope_t.id)
|
||||
s2 = part("Zeta 1-6x24", scope_t.id)
|
||||
s1 = part("Alpha 3-18x50", scope_t.id, manufacturer_id=10, sub_part_type_id=rifle.id)
|
||||
s2 = part("Zeta 1-6x24", scope_t.id, manufacturer_id=20, sub_part_type_id=reddot.id)
|
||||
fc1 = part("Flip cover 50mm", cover_t.id)
|
||||
a1 = part("ARD 50mm", ard_t.id)
|
||||
a2 = part("ARD 56mm", ard_t.id)
|
||||
@@ -58,7 +68,15 @@ async def _seed_guide_data(db):
|
||||
fit(9, 10, fc1, s2, FitLabel.POSSIBLE)
|
||||
await db.commit()
|
||||
|
||||
return {"scope": scope_t, "cover": cover_t, "ard": ard_t, "s1": s1, "s2": s2}
|
||||
return {
|
||||
"scope": scope_t,
|
||||
"cover": cover_t,
|
||||
"ard": ard_t,
|
||||
"s1": s1,
|
||||
"s2": s2,
|
||||
"rifle": rifle,
|
||||
"reddot": reddot,
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@@ -111,6 +129,45 @@ async def test_build_no_scope_type_returns_empty_rows(db_sessionmaker):
|
||||
assert [ct.name for ct in guide["column_types"]] == ["Flip Cover"]
|
||||
|
||||
|
||||
def _descriptions(guide):
|
||||
return [r["scope"].description for r in guide["rows"]]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_build_filters_by_description(db_sessionmaker):
|
||||
async with db_sessionmaker() as db:
|
||||
await _seed_guide_data(db)
|
||||
guide = await scope_guide.build(db, description="alpha")
|
||||
assert _descriptions(guide) == ["Alpha 3-18x50"]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_build_filters_by_manufacturer(db_sessionmaker):
|
||||
async with db_sessionmaker() as db:
|
||||
await _seed_guide_data(db)
|
||||
guide = await scope_guide.build(db, manufacturer_id=20)
|
||||
assert _descriptions(guide) == ["Zeta 1-6x24"]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_build_filters_by_sub_part_type(db_sessionmaker):
|
||||
async with db_sessionmaker() as db:
|
||||
ids = await _seed_guide_data(db)
|
||||
guide = await scope_guide.build(db, sub_part_type_id=ids["rifle"].id)
|
||||
assert _descriptions(guide) == ["Alpha 3-18x50"]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_build_filters_by_required_fit_type(db_sessionmaker):
|
||||
async with db_sessionmaker() as db:
|
||||
ids = await _seed_guide_data(db)
|
||||
# Only Alpha has an ARD fit; both scopes fit a flip cover.
|
||||
ard_only = await scope_guide.build(db, fits_part_type_id=ids["ard"].id)
|
||||
cover = await scope_guide.build(db, fits_part_type_id=ids["cover"].id)
|
||||
assert _descriptions(ard_only) == ["Alpha 3-18x50"]
|
||||
assert _descriptions(cover) == ["Alpha 3-18x50", "Zeta 1-6x24"]
|
||||
|
||||
|
||||
async def _web_login(client, email, password="secret123"):
|
||||
resp = await client.post(
|
||||
"/login", data={"email": email, "password": password}
|
||||
@@ -145,6 +202,30 @@ async def test_scopes_page_renders_rows_and_fits(
|
||||
assert "3–18×" in body # magnification range, integral values un-padded
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_scopes_filter_endpoint_narrows_rows(
|
||||
client, seeded, make_user, db_sessionmaker
|
||||
):
|
||||
async with db_sessionmaker() as db:
|
||||
await _seed_guide_data(db)
|
||||
await make_user("reader3@example.com", role_ids=[seeded["roles"]["user"].id])
|
||||
await _web_login(client, "reader3@example.com")
|
||||
resp = await client.get("/scopes/filter", params={"description": "Alpha"})
|
||||
assert resp.status_code == 200
|
||||
assert "Alpha 3-18x50" in resp.text
|
||||
assert "Zeta 1-6x24" not in resp.text
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_scopes_filter_endpoint_forbidden_without_permission(
|
||||
client, seeded, make_user
|
||||
):
|
||||
await make_user("plain2@example.com") # no roles, not a superuser
|
||||
await _web_login(client, "plain2@example.com")
|
||||
resp = await client.get("/scopes/filter")
|
||||
assert resp.status_code == 403
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_scopes_page_forbidden_without_permission(client, seeded, make_user):
|
||||
await make_user("plain@example.com") # no roles, not a superuser
|
||||
|
||||
Reference in new issue
Block a user