Adding on_website and preferred part indicators
This commit is contained in:
1 parent
13b64a2d17
commit
4fd2bb1b58
13 files changed
+331
-6
No files matched your search
@@ -0,0 +1,41 @@
|
||||
"""augmented_parts_on_website_preferred
|
||||
|
||||
Revision ID: 4d5e6f7a8b9c
|
||||
Revises: 3c4d5e6f7a8b
|
||||
Create Date: 2026-09-21 00:00:00.000000
|
||||
"""
|
||||
|
||||
from collections.abc import Sequence
|
||||
|
||||
import sqlalchemy as sa
|
||||
|
||||
from alembic import op
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = "4d5e6f7a8b9c"
|
||||
down_revision: str | None = "3c4d5e6f7a8b"
|
||||
branch_labels: str | Sequence[str] | None = None
|
||||
depends_on: str | Sequence[str] | None = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
with op.batch_alter_table("augmented_parts", schema=None) as batch_op:
|
||||
batch_op.add_column(
|
||||
sa.Column(
|
||||
"on_website", sa.Boolean(), nullable=False, server_default=sa.false()
|
||||
)
|
||||
)
|
||||
batch_op.add_column(
|
||||
sa.Column(
|
||||
"preferred_part",
|
||||
sa.Boolean(),
|
||||
nullable=False,
|
||||
server_default=sa.false(),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
with op.batch_alter_table("augmented_parts", schema=None) as batch_op:
|
||||
batch_op.drop_column("preferred_part")
|
||||
batch_op.drop_column("on_website")
|
||||
@@ -59,6 +59,8 @@ async def create_augmented_part(
|
||||
scope_model_id=payload.scope_model_id,
|
||||
part_type_id=payload.part_type_id,
|
||||
sub_part_type_id=payload.sub_part_type_id,
|
||||
on_website=payload.on_website,
|
||||
preferred_part=payload.preferred_part,
|
||||
)
|
||||
await audit_crud.log(
|
||||
db,
|
||||
|
||||
@@ -10,7 +10,14 @@ from app.models.part_type import PartType
|
||||
from app.models.scope_model import ScopeModel
|
||||
from app.models.sub_part_type import SubPartType
|
||||
|
||||
_RELATIONSHIPS = ["colour", "manufacturer", "scope_model", "part_type", "sub_part_type"]
|
||||
_RELATIONSHIPS = [
|
||||
"colour",
|
||||
"manufacturer",
|
||||
"scope_model",
|
||||
"part_type",
|
||||
"sub_part_type",
|
||||
"notes",
|
||||
]
|
||||
|
||||
# Sortable columns for the admin list, keyed by the query-string "sort" value.
|
||||
# Columns backed by a related table's name require an outer join (the FK may be
|
||||
@@ -87,6 +94,7 @@ async def list_filtered(
|
||||
part_type_id: int | None = None,
|
||||
sub_part_type_id: int | None = None,
|
||||
include_archived: bool = False,
|
||||
on_website: bool = False,
|
||||
sort: str = "description",
|
||||
direction: str = "asc",
|
||||
skip: int = 0,
|
||||
@@ -110,6 +118,8 @@ async def list_filtered(
|
||||
q = q.where(AugmentedPart.sub_part_type_id == sub_part_type_id)
|
||||
if not include_archived:
|
||||
q = q.where(AugmentedPart.archived.is_(False))
|
||||
if on_website:
|
||||
q = q.where(AugmentedPart.on_website.is_(True))
|
||||
q = _apply_sort(q, sort, direction)
|
||||
result = await db.execute(q.offset(skip).limit(limit))
|
||||
return list(result.scalars().all())
|
||||
@@ -124,6 +134,7 @@ async def count_filtered(
|
||||
part_type_id: int | None = None,
|
||||
sub_part_type_id: int | None = None,
|
||||
include_archived: bool = False,
|
||||
on_website: bool = False,
|
||||
) -> int:
|
||||
from sqlalchemy import func
|
||||
|
||||
@@ -145,6 +156,8 @@ async def count_filtered(
|
||||
q = q.where(AugmentedPart.sub_part_type_id == sub_part_type_id)
|
||||
if not include_archived:
|
||||
q = q.where(AugmentedPart.archived.is_(False))
|
||||
if on_website:
|
||||
q = q.where(AugmentedPart.on_website.is_(True))
|
||||
result = await db.execute(q)
|
||||
return result.scalar_one()
|
||||
|
||||
@@ -220,6 +233,8 @@ async def create(
|
||||
scope_model_id: int | None,
|
||||
part_type_id: int,
|
||||
sub_part_type_id: int | None,
|
||||
on_website: bool = False,
|
||||
preferred_part: bool = False,
|
||||
) -> AugmentedPart:
|
||||
ap = AugmentedPart(
|
||||
sku=sku,
|
||||
@@ -229,6 +244,8 @@ async def create(
|
||||
scope_model_id=scope_model_id,
|
||||
part_type_id=part_type_id,
|
||||
sub_part_type_id=sub_part_type_id,
|
||||
on_website=on_website,
|
||||
preferred_part=preferred_part,
|
||||
)
|
||||
db.add(ap)
|
||||
await db.commit()
|
||||
|
||||
@@ -47,6 +47,8 @@ class AugmentedPart(Base):
|
||||
# removed, so fit/attachment-point history is preserved. Hidden from list
|
||||
# views by default.
|
||||
archived: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
|
||||
on_website: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
|
||||
preferred_part: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
|
||||
|
||||
# linked imported parts — not eagerly loaded; used by sync service only
|
||||
imported_parts: Mapped[list[ImportedPart]] = relationship(
|
||||
|
||||
@@ -39,6 +39,8 @@ class AugmentedPartBase(BaseModel):
|
||||
scope_model_id: int | None = None
|
||||
part_type_id: int
|
||||
sub_part_type_id: int | None = None
|
||||
on_website: bool = False
|
||||
preferred_part: bool = False
|
||||
|
||||
|
||||
class AugmentedPartCreate(AugmentedPartBase):
|
||||
@@ -54,6 +56,8 @@ class AugmentedPartUpdate(BaseModel):
|
||||
part_type_id: int | None = None
|
||||
sub_part_type_id: int | None = None
|
||||
archived: bool | None = None
|
||||
on_website: bool | None = None
|
||||
preferred_part: bool | None = None
|
||||
|
||||
|
||||
class AugmentedPartSyncResult(BaseModel):
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
<td>{{ ap.part_type.name }}</td>
|
||||
<td>{{ ap.sub_part_type.name if ap.sub_part_type else '—' }}</td>
|
||||
<td>{% if ap.archived %}<span class="tag">Archived</span>{% else %}—{% endif %}</td>
|
||||
<td>{% if ap.on_website %}<span class="tag">Yes</span>{% else %}—{% endif %}</td>
|
||||
<td>{% if ap.preferred_part %}<span class="tag">Yes</span>{% else %}—{% endif %}</td>
|
||||
<td class="row-actions">
|
||||
<button class="btn btn-ghost"
|
||||
hx-get="/admin/augmented-parts/{{ ap.id }}/edit"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<tr id="augmented-part-{{ ap.id }}">
|
||||
<td colspan="10">
|
||||
<td colspan="12">
|
||||
<form id="augmented-part-edit-form-{{ ap.id }}"
|
||||
hx-post="/admin/augmented-parts/{{ ap.id }}"
|
||||
hx-target="#augmented-part-{{ ap.id }}"
|
||||
@@ -45,6 +45,8 @@
|
||||
{% endfor %}
|
||||
</select>
|
||||
</label>
|
||||
<label class="check"><input type="checkbox" name="on_website" value="true" {{ "checked" if ap.on_website }}> On website</label>
|
||||
<label class="check"><input type="checkbox" name="preferred_part" value="true" {{ "checked" if ap.preferred_part }}> Preferred part</label>
|
||||
<div class="row-actions">
|
||||
<button type="submit" class="btn btn-primary">Save</button>
|
||||
<button type="button" class="btn btn-ghost"
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
{% endfor %}
|
||||
</select>
|
||||
<label><input type="checkbox" name="include_archived" {{ "checked" if include_archived }}> Show archived</label>
|
||||
<label><input type="checkbox" name="on_website" {{ "checked" if on_website }}> On website</label>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
{{ sort_th("part_type", "Type", sort_headers) }}
|
||||
{{ sort_th("sub_part_type", "Sub Type", sort_headers) }}
|
||||
<th>Archived</th>
|
||||
<th>On Website</th>
|
||||
<th>Preferred</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -20,7 +22,7 @@
|
||||
{% for ap in augmented_parts %}
|
||||
{% include "admin/_augmented_part_row.html" %}
|
||||
{% else %}
|
||||
<tr><td colspan="10" class="muted">No augmented parts recorded.</td></tr>
|
||||
<tr><td colspan="12" class="muted">No augmented parts recorded.</td></tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
<span class="tag">{{ ap.part_type.name }}</span>
|
||||
{% if ap.sub_part_type %}<span class="tag">{{ ap.sub_part_type.name }}</span>{% endif %}
|
||||
{% if ap.archived %}<span class="tag">Archived</span>{% endif %}
|
||||
{% if ap.on_website %}<span class="tag">On website</span>{% endif %}
|
||||
{% if ap.preferred_part %}<span class="tag">Preferred</span>{% endif %}
|
||||
{% if ap.description %}{{ ap.description }}{% endif %}
|
||||
</p>
|
||||
|
||||
|
||||
@@ -50,6 +50,8 @@
|
||||
{% endfor %}
|
||||
</select>
|
||||
</label>
|
||||
<label class="check"><input type="checkbox" name="on_website" value="true"> On website</label>
|
||||
<label class="check"><input type="checkbox" name="preferred_part" value="true"> Preferred part</label>
|
||||
<button type="submit" class="btn btn-primary">Add</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
+25
-3
@@ -1674,6 +1674,7 @@ async def _default_augmented_parts_table_ctx(db: AsyncSession) -> dict:
|
||||
"sort": "description",
|
||||
"dir": "asc",
|
||||
"include_archived": False,
|
||||
"on_website": False,
|
||||
}
|
||||
|
||||
|
||||
@@ -1683,23 +1684,30 @@ async def augmented_parts_page(
|
||||
sort: str = "description",
|
||||
dir: str = "asc",
|
||||
include_archived: bool = False,
|
||||
on_website: bool = False,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
user: User = Depends(web_require("augmented_parts:read")),
|
||||
):
|
||||
ctx = await _augmented_part_form_ctx(db)
|
||||
total = await augmented_part_crud.count_filtered(
|
||||
db, include_archived=include_archived
|
||||
db, include_archived=include_archived, on_website=on_website
|
||||
)
|
||||
ctx["augmented_parts"] = await augmented_part_crud.list_filtered(
|
||||
db,
|
||||
sort=sort,
|
||||
direction=dir,
|
||||
include_archived=include_archived,
|
||||
on_website=on_website,
|
||||
limit=_PAGE_SIZE,
|
||||
)
|
||||
ctx["pagination"] = _paginate(
|
||||
"/admin/augmented-parts/filter",
|
||||
{"sort": sort, "dir": dir, "include_archived": include_archived},
|
||||
{
|
||||
"sort": sort,
|
||||
"dir": dir,
|
||||
"include_archived": include_archived,
|
||||
"on_website": on_website,
|
||||
},
|
||||
1,
|
||||
_PAGE_SIZE,
|
||||
total,
|
||||
@@ -1707,7 +1715,7 @@ async def augmented_parts_page(
|
||||
)
|
||||
ctx["sort_headers"] = _sort_headers(
|
||||
"/admin/augmented-parts/filter",
|
||||
{"include_archived": include_archived},
|
||||
{"include_archived": include_archived, "on_website": on_website},
|
||||
_AUGMENTED_PARTS_SORT_COLUMNS,
|
||||
sort,
|
||||
dir,
|
||||
@@ -1716,6 +1724,7 @@ async def augmented_parts_page(
|
||||
ctx["sort"] = sort
|
||||
ctx["dir"] = dir
|
||||
ctx["include_archived"] = include_archived
|
||||
ctx["on_website"] = on_website
|
||||
ctx["user"] = user
|
||||
return templates.TemplateResponse(request, "admin/augmented_parts.html", ctx)
|
||||
|
||||
@@ -1730,6 +1739,8 @@ async def create_augmented_part(
|
||||
scope_model_id: str = Form(""),
|
||||
part_type_id: int = Form(...),
|
||||
sub_part_type_id: str = Form(""),
|
||||
on_website: bool = Form(False),
|
||||
preferred_part: bool = Form(False),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
actor: User = Depends(web_require("augmented_parts:write")),
|
||||
):
|
||||
@@ -1745,6 +1756,8 @@ async def create_augmented_part(
|
||||
scope_model_id=int(scope_model_id) if scope_model_id else None,
|
||||
part_type_id=part_type_id,
|
||||
sub_part_type_id=int(sub_part_type_id) if sub_part_type_id else None,
|
||||
on_website=on_website,
|
||||
preferred_part=preferred_part,
|
||||
)
|
||||
await audit_crud.log(
|
||||
db,
|
||||
@@ -1874,6 +1887,7 @@ async def filter_augmented_parts(
|
||||
part_type_id: str = "",
|
||||
sub_part_type_id: str = "",
|
||||
include_archived: bool = False,
|
||||
on_website: bool = False,
|
||||
sort: str = "description",
|
||||
dir: str = "asc",
|
||||
page: int = 1,
|
||||
@@ -1895,6 +1909,7 @@ async def filter_augmented_parts(
|
||||
part_type_id=part_type_id_int,
|
||||
sub_part_type_id=sub_part_type_id_int,
|
||||
include_archived=include_archived,
|
||||
on_website=on_website,
|
||||
)
|
||||
filter_params = {
|
||||
"description": description,
|
||||
@@ -1904,6 +1919,7 @@ async def filter_augmented_parts(
|
||||
"part_type_id": part_type_id,
|
||||
"sub_part_type_id": sub_part_type_id,
|
||||
"include_archived": include_archived,
|
||||
"on_website": on_website,
|
||||
}
|
||||
pagination = _paginate(
|
||||
"/admin/augmented-parts/filter",
|
||||
@@ -1922,6 +1938,7 @@ async def filter_augmented_parts(
|
||||
part_type_id=part_type_id_int,
|
||||
sub_part_type_id=sub_part_type_id_int,
|
||||
include_archived=include_archived,
|
||||
on_website=on_website,
|
||||
sort=sort,
|
||||
direction=dir,
|
||||
skip=pagination["skip"],
|
||||
@@ -1945,6 +1962,7 @@ async def filter_augmented_parts(
|
||||
"sort": sort,
|
||||
"dir": dir,
|
||||
"include_archived": include_archived,
|
||||
"on_website": on_website,
|
||||
},
|
||||
)
|
||||
|
||||
@@ -2188,6 +2206,8 @@ async def update_augmented_part(
|
||||
scope_model_id: str = Form(""),
|
||||
part_type_id: int = Form(...),
|
||||
sub_part_type_id: str = Form(""),
|
||||
on_website: bool = Form(False),
|
||||
preferred_part: bool = Form(False),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
actor: User = Depends(web_require("augmented_parts:write")),
|
||||
):
|
||||
@@ -2207,6 +2227,8 @@ async def update_augmented_part(
|
||||
"scope_model_id": int(scope_model_id) if scope_model_id else None,
|
||||
"part_type_id": part_type_id,
|
||||
"sub_part_type_id": int(sub_part_type_id) if sub_part_type_id else None,
|
||||
"on_website": on_website,
|
||||
"preferred_part": preferred_part,
|
||||
}
|
||||
await augmented_part_crud.update(db, ap, changes)
|
||||
await audit_crud.log(
|
||||
|
||||
@@ -0,0 +1,226 @@
|
||||
"""`on_website` and `preferred_part` booleans on AugmentedPart: default to
|
||||
False, settable via create/update (API + admin web UI), and `on_website`
|
||||
is filterable in the admin listing."""
|
||||
|
||||
import pytest
|
||||
|
||||
from app.models.augmented_part import AugmentedPart
|
||||
from app.models.manufacturer import Manufacturer
|
||||
from app.models.part_colour import PartColour
|
||||
from app.models.part_type import PartType
|
||||
|
||||
|
||||
async def _seed_reference_data(db):
|
||||
manufacturer = Manufacturer(name="Acme", url="https://acme.test")
|
||||
colour = PartColour(name="Black")
|
||||
part_type = PartType(name="Scope")
|
||||
db.add_all([manufacturer, colour, part_type])
|
||||
await db.flush()
|
||||
return manufacturer, colour, part_type
|
||||
|
||||
|
||||
async def _token(client, email, password="secret123"):
|
||||
resp = await client.post(
|
||||
"/api/auth/login", data={"username": email, "password": password}
|
||||
)
|
||||
assert resp.status_code == 200, resp.text
|
||||
return resp.json()["access_token"]
|
||||
|
||||
|
||||
async def _superuser_headers(client, make_user, email):
|
||||
await make_user(email, is_superuser=True)
|
||||
return {"Authorization": f"Bearer {await _token(client, email)}"}
|
||||
|
||||
|
||||
async def _web_login(client, email, password="secret123"):
|
||||
resp = await client.post("/login", data={"email": email, "password": password})
|
||||
assert resp.status_code == 303
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_api_create_defaults_both_fields_to_false(
|
||||
client, seeded, make_user, db_sessionmaker
|
||||
):
|
||||
async with db_sessionmaker() as db:
|
||||
manufacturer, colour, part_type = await _seed_reference_data(db)
|
||||
manufacturer_id, colour_id, part_type_id = (
|
||||
manufacturer.id,
|
||||
colour.id,
|
||||
part_type.id,
|
||||
)
|
||||
await db.commit()
|
||||
|
||||
headers = await _superuser_headers(client, make_user, "owp-api1@example.com")
|
||||
resp = await client.post(
|
||||
"/api/augmented-parts",
|
||||
json={
|
||||
"description": "Widget",
|
||||
"colour_id": colour_id,
|
||||
"manufacturer_id": manufacturer_id,
|
||||
"part_type_id": part_type_id,
|
||||
},
|
||||
headers=headers,
|
||||
)
|
||||
assert resp.status_code == 201, resp.text
|
||||
body = resp.json()
|
||||
assert body["on_website"] is False
|
||||
assert body["preferred_part"] is False
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_api_create_and_update_can_set_both_fields(
|
||||
client, seeded, make_user, db_sessionmaker
|
||||
):
|
||||
async with db_sessionmaker() as db:
|
||||
manufacturer, colour, part_type = await _seed_reference_data(db)
|
||||
manufacturer_id, colour_id, part_type_id = (
|
||||
manufacturer.id,
|
||||
colour.id,
|
||||
part_type.id,
|
||||
)
|
||||
await db.commit()
|
||||
|
||||
headers = await _superuser_headers(client, make_user, "owp-api2@example.com")
|
||||
resp = await client.post(
|
||||
"/api/augmented-parts",
|
||||
json={
|
||||
"description": "Widget",
|
||||
"colour_id": colour_id,
|
||||
"manufacturer_id": manufacturer_id,
|
||||
"part_type_id": part_type_id,
|
||||
"on_website": True,
|
||||
"preferred_part": True,
|
||||
},
|
||||
headers=headers,
|
||||
)
|
||||
assert resp.status_code == 201, resp.text
|
||||
body = resp.json()
|
||||
assert body["on_website"] is True
|
||||
assert body["preferred_part"] is True
|
||||
ap_id = body["id"]
|
||||
|
||||
resp = await client.patch(
|
||||
f"/api/augmented-parts/{ap_id}",
|
||||
json={"on_website": False},
|
||||
headers=headers,
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
body = resp.json()
|
||||
assert body["on_website"] is False
|
||||
assert body["preferred_part"] is True # untouched by the partial update
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_web_admin_create_form_sets_both_checkboxes(
|
||||
client, seeded, make_user, db_sessionmaker
|
||||
):
|
||||
async with db_sessionmaker() as db:
|
||||
manufacturer, colour, part_type = await _seed_reference_data(db)
|
||||
manufacturer_id, colour_id, part_type_id = (
|
||||
manufacturer.id,
|
||||
colour.id,
|
||||
part_type.id,
|
||||
)
|
||||
await db.commit()
|
||||
|
||||
await make_user("owp-web1@example.com", role_ids=[seeded["roles"]["admin"].id])
|
||||
await _web_login(client, "owp-web1@example.com")
|
||||
|
||||
resp = await client.post(
|
||||
"/admin/augmented-parts",
|
||||
data={
|
||||
"description": "Web widget",
|
||||
"colour_id": colour_id,
|
||||
"manufacturer_id": manufacturer_id,
|
||||
"part_type_id": part_type_id,
|
||||
"on_website": "true",
|
||||
"preferred_part": "true",
|
||||
},
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
assert "Web widget" in resp.text
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_web_admin_update_form_toggles_both_fields(
|
||||
client, seeded, make_user, db_sessionmaker
|
||||
):
|
||||
async with db_sessionmaker() as db:
|
||||
manufacturer, colour, part_type = await _seed_reference_data(db)
|
||||
ap = AugmentedPart(
|
||||
description="Togglable widget",
|
||||
colour_id=colour.id,
|
||||
manufacturer_id=manufacturer.id,
|
||||
part_type_id=part_type.id,
|
||||
on_website=False,
|
||||
preferred_part=False,
|
||||
)
|
||||
db.add(ap)
|
||||
await db.commit()
|
||||
ap_id, manufacturer_id, colour_id, part_type_id = (
|
||||
ap.id,
|
||||
manufacturer.id,
|
||||
colour.id,
|
||||
part_type.id,
|
||||
)
|
||||
|
||||
await make_user("owp-web2@example.com", role_ids=[seeded["roles"]["admin"].id])
|
||||
await _web_login(client, "owp-web2@example.com")
|
||||
|
||||
resp = await client.post(
|
||||
f"/admin/augmented-parts/{ap_id}",
|
||||
data={
|
||||
"description": "Togglable widget",
|
||||
"colour_id": colour_id,
|
||||
"manufacturer_id": manufacturer_id,
|
||||
"part_type_id": part_type_id,
|
||||
"on_website": "true",
|
||||
# preferred_part omitted, as an unchecked checkbox would be
|
||||
},
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
|
||||
async with db_sessionmaker() as db:
|
||||
refreshed = await db.get(AugmentedPart, ap_id)
|
||||
assert refreshed.on_website is True
|
||||
assert refreshed.preferred_part is False
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_web_admin_filter_by_on_website(
|
||||
client, seeded, make_user, db_sessionmaker
|
||||
):
|
||||
async with db_sessionmaker() as db:
|
||||
manufacturer, colour, part_type = await _seed_reference_data(db)
|
||||
on_site = AugmentedPart(
|
||||
description="On-site widget",
|
||||
colour_id=colour.id,
|
||||
manufacturer_id=manufacturer.id,
|
||||
part_type_id=part_type.id,
|
||||
on_website=True,
|
||||
)
|
||||
off_site = AugmentedPart(
|
||||
description="Off-site widget",
|
||||
colour_id=colour.id,
|
||||
manufacturer_id=manufacturer.id,
|
||||
part_type_id=part_type.id,
|
||||
on_website=False,
|
||||
)
|
||||
db.add_all([on_site, off_site])
|
||||
await db.commit()
|
||||
|
||||
await make_user("owp-web3@example.com", role_ids=[seeded["roles"]["admin"].id])
|
||||
await _web_login(client, "owp-web3@example.com")
|
||||
|
||||
resp = await client.get("/admin/augmented-parts")
|
||||
assert "On-site widget" in resp.text
|
||||
assert "Off-site widget" in resp.text
|
||||
|
||||
resp = await client.get("/admin/augmented-parts/filter?on_website=true")
|
||||
assert resp.status_code == 200
|
||||
assert "On-site widget" in resp.text
|
||||
assert "Off-site widget" not in resp.text
|
||||
|
||||
resp = await client.get("/admin/augmented-parts/filter")
|
||||
assert "On-site widget" in resp.text
|
||||
assert "Off-site widget" in resp.text
|
||||
Reference in new issue
Block a user