Match the optional identifiers in every list's search box
gaugelabreference and maintenancereference are collected on the form and shown on the detail page for all five asset types, and no list's ?search= matched either. Someone holding a physical tag could read it off the machine, type it into the list they were already looking at, and get nothing back - while global search, fixed in the previous commit, found it. The clause is copy-pasted once per plugin, which is how all five came to omit fields their own forms collect, so the test is one parametrized pass over all five lists rather than five per-plugin tests that would drift the same way. It also pins that widening the clause did not turn the box into a pass-through. The api-inventory entries enumerate the fields each search matches, so all five were stale the moment the queries changed; updated with the OpenAPI spec. Not touched: the collector does not send either identifier, correctly - a lab-assigned tag is not something an agent on a PC can discover. The legacy import loader does not map them either, and the classic schema has no gauge-named column to map from.
This commit is contained in:
@@ -85,6 +85,6 @@ Manifest-less directories under `plugins/` are core frontend surface and always
|
|||||||
|
|
||||||
## Size
|
## Size
|
||||||
|
|
||||||
- test functions defined: **1084** (parametrised cases collect higher)
|
- test functions defined: **1087** (parametrised cases collect higher)
|
||||||
- documented API paths: **276** (`docs/openapi.json`, regenerate with `scripts/gen_openapi.py`)
|
- documented API paths: **276** (`docs/openapi.json`, regenerate with `scripts/gen_openapi.py`)
|
||||||
|
|
||||||
|
|||||||
@@ -1582,7 +1582,7 @@
|
|||||||
"method": "GET",
|
"method": "GET",
|
||||||
"path": "/api/computers",
|
"path": "/api/computers",
|
||||||
"auth": "jwt-optional",
|
"auth": "jwt-optional",
|
||||||
"params": "page, per_page, active, search (assetnumber/name/serialnumber/hostname ilike), assetnumber (exact, for idempotent import), typeid|type_id, osid|os_id, locationid|location_id, businessunitid|businessunit_id, shopfloor (true/false), sort (hostname|assetnumber|name|lastreporteddate), dir (asc|desc)",
|
"params": "page, per_page, active, search (assetnumber/name/serialnumber/hostname/gaugelabreference/maintenancereference ilike), assetnumber (exact, for idempotent import), typeid|type_id, osid|os_id, locationid|location_id, businessunitid|businessunit_id, shopfloor (true/false), sort (hostname|assetnumber|name|lastreporteddate), dir (asc|desc)",
|
||||||
"purpose": "List computers (asset + computer + resolved access links), filtered and paginated",
|
"purpose": "List computers (asset + computer + resolved access links), filtered and paginated",
|
||||||
"example": "curl 'http://localhost:5001/api/computers?shopfloor=true&sort=lastreporteddate&dir=desc&per_page=25'"
|
"example": "curl 'http://localhost:5001/api/computers?shopfloor=true&sort=lastreporteddate&dir=desc&per_page=25'"
|
||||||
},
|
},
|
||||||
@@ -1749,7 +1749,7 @@
|
|||||||
"path": "/api/measuringtools",
|
"path": "/api/measuringtools",
|
||||||
"purpose": "List measuring tools (Asset core merged with extension), filtered + paginated; derived calibrationstatus filter applied post-pagination.",
|
"purpose": "List measuring tools (Asset core merged with extension), filtered + paginated; derived calibrationstatus filter applied post-pagination.",
|
||||||
"auth": "jwt-optional",
|
"auth": "jwt-optional",
|
||||||
"params": "query: active (default true), assetnumber (exact match, for idempotent import), search (assetnumber/name/serialnumber ilike), typeid, locationid, statusid, calibrationstatus (overdue|duesoon|current|unknown), page, perpage",
|
"params": "query: active (default true), assetnumber (exact match, for idempotent import), search (assetnumber/name/serialnumber/gaugelabreference/maintenancereference ilike), typeid, locationid, statusid, calibrationstatus (overdue|duesoon|current|unknown), page, perpage",
|
||||||
"example": "curl 'http://localhost:5001/api/measuringtools?typeid=2&calibrationstatus=overdue&page=1&perpage=50'"
|
"example": "curl 'http://localhost:5001/api/measuringtools?typeid=2&calibrationstatus=overdue&page=1&perpage=50'"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1858,7 +1858,7 @@
|
|||||||
"path": "/api/machines",
|
"path": "/api/machines",
|
||||||
"purpose": "List machines (Asset+Machine join) with filters, sorting, pagination; collapses Dualpath dual-bay pairs to one row (annotated with dualpathpartner) when site setting enabled",
|
"purpose": "List machines (Asset+Machine join) with filters, sorting, pagination; collapses Dualpath dual-bay pairs to one row (annotated with dualpathpartner) when site setting enabled",
|
||||||
"auth": "jwt-optional",
|
"auth": "jwt-optional",
|
||||||
"params": "query: page, per_page, active ('false' includes inactive), assetnumber (exact-match for idempotent import), search (assetnumber/name/serialnumber ilike), typeid|type_id, vendorid|vendor_id, locationid|location_id, businessunitid|businessunit_id, sort (assetnumber|name), dir (asc|desc)",
|
"params": "query: page, per_page, active ('false' includes inactive), assetnumber (exact-match for idempotent import), search (assetnumber/name/serialnumber/gaugelabreference/maintenancereference ilike), typeid|type_id, vendorid|vendor_id, locationid|location_id, businessunitid|businessunit_id, sort (assetnumber|name), dir (asc|desc)",
|
||||||
"example": "curl 'http://localhost:5001/api/machines?search=2007&typeid=2&sort=name&dir=desc&page=1&per_page=50'"
|
"example": "curl 'http://localhost:5001/api/machines?search=2007&typeid=2&sort=name&dir=desc&page=1&per_page=50'"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -2546,7 +2546,7 @@
|
|||||||
"path": "/api/network",
|
"path": "/api/network",
|
||||||
"purpose": "List network devices (Asset joined with NetworkDevice extension + primary IP), filtered/sorted/paginated",
|
"purpose": "List network devices (Asset joined with NetworkDevice extension + primary IP), filtered/sorted/paginated",
|
||||||
"auth": "jwt-optional",
|
"auth": "jwt-optional",
|
||||||
"params": "page, per_page, active, assetnumber (exact match for idempotent import), search (assetnumber/name/serialnumber/hostname), typeid|type_id, vendorid|vendor_id, locationid|location_id, businessunitid|businessunit_id, poe (true/false), managed (true/false), sort (hostname|assetnumber|name), dir (asc|desc)",
|
"params": "page, per_page, active, assetnumber (exact match for idempotent import), search (assetnumber/name/serialnumber/hostname/gaugelabreference/maintenancereference), typeid|type_id, vendorid|vendor_id, locationid|location_id, businessunitid|businessunit_id, poe (true/false), managed (true/false), sort (hostname|assetnumber|name), dir (asc|desc)",
|
||||||
"example": "curl 'http://localhost:5001/api/network?typeid=2&poe=true&sort=hostname&dir=asc'"
|
"example": "curl 'http://localhost:5001/api/network?typeid=2&poe=true&sort=hostname&dir=asc'"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -2852,7 +2852,7 @@
|
|||||||
"method": "GET",
|
"method": "GET",
|
||||||
"path": "/api/printers",
|
"path": "/api/printers",
|
||||||
"auth": "jwt-optional",
|
"auth": "jwt-optional",
|
||||||
"params": "page, per_page, active, assetnumber (exact-match for import idempotency), search (assetnumber/name/serial/hostname/windowsname), typeid|type_id, vendorid|vendor_id, locationid|location_id, businessunitid|businessunit_id, sort (hostname|assetnumber|name), dir (asc|desc)",
|
"params": "page, per_page, active, assetnumber (exact-match for import idempotency), search (assetnumber/name/serial/hostname/windowsname/gaugelabreference/maintenancereference), typeid|type_id, vendorid|vendor_id, locationid|location_id, businessunitid|businessunit_id, sort (hostname|assetnumber|name), dir (asc|desc)",
|
||||||
"purpose": "List printers (joined Asset+Printer) with filters, search, sorting, pagination; each row includes primary IP.",
|
"purpose": "List printers (joined Asset+Printer) with filters, search, sorting, pagination; each row includes primary IP.",
|
||||||
"example": "curl 'http://localhost:5001/api/printers?search=csf&typeid=2&sort=assetnumber&dir=desc'"
|
"example": "curl 'http://localhost:5001/api/printers?search=csf&typeid=2&sort=assetnumber&dir=desc'"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -9231,7 +9231,7 @@
|
|||||||
"plugin-computers"
|
"plugin-computers"
|
||||||
],
|
],
|
||||||
"summary": "List computers (asset + computer + resolved access links), filtered and paginated",
|
"summary": "List computers (asset + computer + resolved access links), filtered and paginated",
|
||||||
"description": "List computers (asset + computer + resolved access links), filtered and paginated\n\n**Auth:** jwt-optional\n\n**Params:** page, per_page, active, search (assetnumber/name/serialnumber/hostname ilike), assetnumber (exact, for idempotent import), typeid|type_id, osid|os_id, locationid|location_id, businessunitid|businessunit_id, shopfloor (true/false), sort (hostname|assetnumber|name|lastreporteddate), dir (asc|desc)\n\n**Example:**\n```\ncurl 'http://localhost:5001/api/computers?shopfloor=true&sort=lastreporteddate&dir=desc&per_page=25'\n```",
|
"description": "List computers (asset + computer + resolved access links), filtered and paginated\n\n**Auth:** jwt-optional\n\n**Params:** page, per_page, active, search (assetnumber/name/serialnumber/hostname/gaugelabreference/maintenancereference ilike), assetnumber (exact, for idempotent import), typeid|type_id, osid|os_id, locationid|location_id, businessunitid|businessunit_id, shopfloor (true/false), sort (hostname|assetnumber|name|lastreporteddate), dir (asc|desc)\n\n**Example:**\n```\ncurl 'http://localhost:5001/api/computers?shopfloor=true&sort=lastreporteddate&dir=desc&per_page=25'\n```",
|
||||||
"security": [
|
"security": [
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
@@ -10135,7 +10135,7 @@
|
|||||||
"plugin-measuringtools"
|
"plugin-measuringtools"
|
||||||
],
|
],
|
||||||
"summary": "List measuring tools (Asset core merged with extension), filtered + paginated; derived calibrationstatus filter applied...",
|
"summary": "List measuring tools (Asset core merged with extension), filtered + paginated; derived calibrationstatus filter applied...",
|
||||||
"description": "List measuring tools (Asset core merged with extension), filtered + paginated; derived calibrationstatus filter applied post-pagination.\n\n**Auth:** jwt-optional\n\n**Params:** query: active (default true), assetnumber (exact match, for idempotent import), search (assetnumber/name/serialnumber ilike), typeid, locationid, statusid, calibrationstatus (overdue|duesoon|current|unknown), page, perpage\n\n**Example:**\n```\ncurl 'http://localhost:5001/api/measuringtools?typeid=2&calibrationstatus=overdue&page=1&perpage=50'\n```",
|
"description": "List measuring tools (Asset core merged with extension), filtered + paginated; derived calibrationstatus filter applied post-pagination.\n\n**Auth:** jwt-optional\n\n**Params:** query: active (default true), assetnumber (exact match, for idempotent import), search (assetnumber/name/serialnumber/gaugelabreference/maintenancereference ilike), typeid, locationid, statusid, calibrationstatus (overdue|duesoon|current|unknown), page, perpage\n\n**Example:**\n```\ncurl 'http://localhost:5001/api/measuringtools?typeid=2&calibrationstatus=overdue&page=1&perpage=50'\n```",
|
||||||
"security": [
|
"security": [
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
@@ -10721,7 +10721,7 @@
|
|||||||
"plugin-machines"
|
"plugin-machines"
|
||||||
],
|
],
|
||||||
"summary": "List machines (Asset+Machine join) with filters, sorting, pagination; collapses Dualpath dual-bay pairs to one row...",
|
"summary": "List machines (Asset+Machine join) with filters, sorting, pagination; collapses Dualpath dual-bay pairs to one row...",
|
||||||
"description": "List machines (Asset+Machine join) with filters, sorting, pagination; collapses Dualpath dual-bay pairs to one row (annotated with dualpathpartner) when site setting enabled\n\n**Auth:** jwt-optional\n\n**Params:** query: page, per_page, active ('false' includes inactive), assetnumber (exact-match for idempotent import), search (assetnumber/name/serialnumber ilike), typeid|type_id, vendorid|vendor_id, locationid|location_id, businessunitid|businessunit_id, sort (assetnumber|name), dir (asc|desc)\n\n**Example:**\n```\ncurl 'http://localhost:5001/api/machines?search=2007&typeid=2&sort=name&dir=desc&page=1&per_page=50'\n```",
|
"description": "List machines (Asset+Machine join) with filters, sorting, pagination; collapses Dualpath dual-bay pairs to one row (annotated with dualpathpartner) when site setting enabled\n\n**Auth:** jwt-optional\n\n**Params:** query: page, per_page, active ('false' includes inactive), assetnumber (exact-match for idempotent import), search (assetnumber/name/serialnumber/gaugelabreference/maintenancereference ilike), typeid|type_id, vendorid|vendor_id, locationid|location_id, businessunitid|businessunit_id, sort (assetnumber|name), dir (asc|desc)\n\n**Example:**\n```\ncurl 'http://localhost:5001/api/machines?search=2007&typeid=2&sort=name&dir=desc&page=1&per_page=50'\n```",
|
||||||
"security": [
|
"security": [
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
@@ -14788,7 +14788,7 @@
|
|||||||
"plugin-network"
|
"plugin-network"
|
||||||
],
|
],
|
||||||
"summary": "List network devices (Asset joined with NetworkDevice extension + primary IP), filtered/sorted/paginated",
|
"summary": "List network devices (Asset joined with NetworkDevice extension + primary IP), filtered/sorted/paginated",
|
||||||
"description": "List network devices (Asset joined with NetworkDevice extension + primary IP), filtered/sorted/paginated\n\n**Auth:** jwt-optional\n\n**Params:** page, per_page, active, assetnumber (exact match for idempotent import), search (assetnumber/name/serialnumber/hostname), typeid|type_id, vendorid|vendor_id, locationid|location_id, businessunitid|businessunit_id, poe (true/false), managed (true/false), sort (hostname|assetnumber|name), dir (asc|desc)\n\n**Example:**\n```\ncurl 'http://localhost:5001/api/network?typeid=2&poe=true&sort=hostname&dir=asc'\n```",
|
"description": "List network devices (Asset joined with NetworkDevice extension + primary IP), filtered/sorted/paginated\n\n**Auth:** jwt-optional\n\n**Params:** page, per_page, active, assetnumber (exact match for idempotent import), search (assetnumber/name/serialnumber/hostname/gaugelabreference/maintenancereference), typeid|type_id, vendorid|vendor_id, locationid|location_id, businessunitid|businessunit_id, poe (true/false), managed (true/false), sort (hostname|assetnumber|name), dir (asc|desc)\n\n**Example:**\n```\ncurl 'http://localhost:5001/api/network?typeid=2&poe=true&sort=hostname&dir=asc'\n```",
|
||||||
"security": [
|
"security": [
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
@@ -16543,7 +16543,7 @@
|
|||||||
"plugin-printers"
|
"plugin-printers"
|
||||||
],
|
],
|
||||||
"summary": "List printers (joined Asset+Printer) with filters, search, sorting, pagination; each row includes primary IP.",
|
"summary": "List printers (joined Asset+Printer) with filters, search, sorting, pagination; each row includes primary IP.",
|
||||||
"description": "List printers (joined Asset+Printer) with filters, search, sorting, pagination; each row includes primary IP.\n\n**Auth:** jwt-optional\n\n**Params:** page, per_page, active, assetnumber (exact-match for import idempotency), search (assetnumber/name/serial/hostname/windowsname), typeid|type_id, vendorid|vendor_id, locationid|location_id, businessunitid|businessunit_id, sort (hostname|assetnumber|name), dir (asc|desc)\n\n**Example:**\n```\ncurl 'http://localhost:5001/api/printers?search=csf&typeid=2&sort=assetnumber&dir=desc'\n```",
|
"description": "List printers (joined Asset+Printer) with filters, search, sorting, pagination; each row includes primary IP.\n\n**Auth:** jwt-optional\n\n**Params:** page, per_page, active, assetnumber (exact-match for import idempotency), search (assetnumber/name/serial/hostname/windowsname/gaugelabreference/maintenancereference), typeid|type_id, vendorid|vendor_id, locationid|location_id, businessunitid|businessunit_id, sort (hostname|assetnumber|name), dir (asc|desc)\n\n**Example:**\n```\ncurl 'http://localhost:5001/api/printers?search=csf&typeid=2&sort=assetnumber&dir=desc'\n```",
|
||||||
"security": [
|
"security": [
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -375,6 +375,11 @@ def list_computers():
|
|||||||
Asset.assetnumber.ilike(pattern),
|
Asset.assetnumber.ilike(pattern),
|
||||||
Asset.name.ilike(pattern),
|
Asset.name.ilike(pattern),
|
||||||
Asset.serialnumber.ilike(pattern),
|
Asset.serialnumber.ilike(pattern),
|
||||||
|
# The optional identifiers too (ADR-001). Global search matches
|
||||||
|
# these, and a tag read off the machine has to find it here as
|
||||||
|
# well - this box is where someone holding the label looks.
|
||||||
|
Asset.gaugelabreference.ilike(pattern),
|
||||||
|
Asset.maintenancereference.ilike(pattern),
|
||||||
Computer.hostname.ilike(pattern),
|
Computer.hostname.ilike(pattern),
|
||||||
ComputerType.computertype.ilike(pattern)
|
ComputerType.computertype.ilike(pattern)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -189,6 +189,11 @@ def list_machines():
|
|||||||
Asset.assetnumber.ilike(pattern),
|
Asset.assetnumber.ilike(pattern),
|
||||||
Asset.name.ilike(pattern),
|
Asset.name.ilike(pattern),
|
||||||
Asset.serialnumber.ilike(pattern),
|
Asset.serialnumber.ilike(pattern),
|
||||||
|
# The optional identifiers too (ADR-001). Global search matches
|
||||||
|
# these, and a tag read off the machine has to find it here as
|
||||||
|
# well - this box is where someone holding the label looks.
|
||||||
|
Asset.gaugelabreference.ilike(pattern),
|
||||||
|
Asset.maintenancereference.ilike(pattern),
|
||||||
MachineType.machinetype.ilike(pattern),
|
MachineType.machinetype.ilike(pattern),
|
||||||
Vendor.vendor.ilike(pattern)
|
Vendor.vendor.ilike(pattern)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -179,6 +179,11 @@ def list_tools():
|
|||||||
Asset.assetnumber.ilike(pattern),
|
Asset.assetnumber.ilike(pattern),
|
||||||
Asset.name.ilike(pattern),
|
Asset.name.ilike(pattern),
|
||||||
Asset.serialnumber.ilike(pattern),
|
Asset.serialnumber.ilike(pattern),
|
||||||
|
# The optional identifiers too (ADR-001). Global search matches
|
||||||
|
# these, and a tag read off the machine has to find it here as
|
||||||
|
# well - this box is where someone holding the label looks.
|
||||||
|
Asset.gaugelabreference.ilike(pattern),
|
||||||
|
Asset.maintenancereference.ilike(pattern),
|
||||||
MeasuringToolType.name.ilike(pattern),
|
MeasuringToolType.name.ilike(pattern),
|
||||||
))
|
))
|
||||||
if type_id := request.args.get('typeid', type=int):
|
if type_id := request.args.get('typeid', type=int):
|
||||||
|
|||||||
@@ -223,6 +223,11 @@ def list_network_devices():
|
|||||||
Asset.assetnumber.ilike(pattern),
|
Asset.assetnumber.ilike(pattern),
|
||||||
Asset.name.ilike(pattern),
|
Asset.name.ilike(pattern),
|
||||||
Asset.serialnumber.ilike(pattern),
|
Asset.serialnumber.ilike(pattern),
|
||||||
|
# The optional identifiers too (ADR-001). Global search matches
|
||||||
|
# these, and a tag read off the machine has to find it here as
|
||||||
|
# well - this box is where someone holding the label looks.
|
||||||
|
Asset.gaugelabreference.ilike(pattern),
|
||||||
|
Asset.maintenancereference.ilike(pattern),
|
||||||
NetworkDevice.hostname.ilike(pattern),
|
NetworkDevice.hostname.ilike(pattern),
|
||||||
NetworkDeviceType.networkdevicetype.ilike(pattern),
|
NetworkDeviceType.networkdevicetype.ilike(pattern),
|
||||||
Vendor.vendor.ilike(pattern)
|
Vendor.vendor.ilike(pattern)
|
||||||
|
|||||||
@@ -254,6 +254,11 @@ def list_printers():
|
|||||||
Asset.assetnumber.ilike(pattern),
|
Asset.assetnumber.ilike(pattern),
|
||||||
Asset.name.ilike(pattern),
|
Asset.name.ilike(pattern),
|
||||||
Asset.serialnumber.ilike(pattern),
|
Asset.serialnumber.ilike(pattern),
|
||||||
|
# The optional identifiers too (ADR-001). Global search matches
|
||||||
|
# these, and a tag read off the machine has to find it here as
|
||||||
|
# well - this box is where someone holding the label looks.
|
||||||
|
Asset.gaugelabreference.ilike(pattern),
|
||||||
|
Asset.maintenancereference.ilike(pattern),
|
||||||
Printer.hostname.ilike(pattern),
|
Printer.hostname.ilike(pattern),
|
||||||
Printer.windowsname.ilike(pattern),
|
Printer.windowsname.ilike(pattern),
|
||||||
PrinterType.printertype.ilike(pattern),
|
PrinterType.printertype.ilike(pattern),
|
||||||
|
|||||||
84
tests/test_core/test_list_search_identifiers.py
Normal file
84
tests/test_core/test_list_search_identifiers.py
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
"""Every asset list's search box matches the optional identifiers (ADR-001).
|
||||||
|
|
||||||
|
Settings offers `gaugelabreference` and `maintenancereference` on machines, PCs,
|
||||||
|
printers, network devices and measuring tools. Both were shown on the form and
|
||||||
|
the detail page and neither was matched by any list's `?search=`, so someone
|
||||||
|
holding a physical tag could read it, type it into the list they were already
|
||||||
|
looking at, and get nothing - while global search found it.
|
||||||
|
|
||||||
|
One parametrized test over all five lists on purpose. The search clause is
|
||||||
|
copy-pasted five times, once per plugin, which is exactly how all five came to
|
||||||
|
omit a field their forms collect; a per-plugin test would drift the same way.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from shopdb.core.models import Asset, AssetType
|
||||||
|
|
||||||
|
|
||||||
|
# (list endpoint, create endpoint, assettype)
|
||||||
|
LISTS = [
|
||||||
|
('/api/machines', '/api/machines', 'machine'),
|
||||||
|
('/api/computers', '/api/computers', 'computer'),
|
||||||
|
('/api/printers', '/api/printers', 'printer'),
|
||||||
|
('/api/network', '/api/network', 'network_device'),
|
||||||
|
('/api/measuringtools', '/api/measuringtools', 'measuring_tool'),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def _seed(client, db, auth_headers, createpath, assettype, assetnumber):
|
||||||
|
"""Create one record of this type carrying both identifiers."""
|
||||||
|
if not AssetType.query.filter_by(assettype=assettype).first():
|
||||||
|
db.session.add(AssetType(assettype=assettype, pluginname=assettype,
|
||||||
|
tablename=assettype, description=assettype))
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
resp = client.post(createpath, json={'assetnumber': assetnumber},
|
||||||
|
headers=auth_headers)
|
||||||
|
assert resp.status_code == 201, (createpath, resp.get_json())
|
||||||
|
|
||||||
|
asset = Asset.query.filter_by(assetnumber=assetnumber).first()
|
||||||
|
asset.gaugelabreference = f'ZZG{assetnumber}'
|
||||||
|
asset.maintenancereference = f'ZZM{assetnumber}'
|
||||||
|
db.session.commit()
|
||||||
|
return asset
|
||||||
|
|
||||||
|
|
||||||
|
def _numbers(client, auth_headers, listpath, query):
|
||||||
|
"""Asset numbers a list returns for a search term."""
|
||||||
|
resp = client.get(f'{listpath}?search={query}', headers=auth_headers)
|
||||||
|
assert resp.status_code == 200, (listpath, resp.get_json())
|
||||||
|
found = []
|
||||||
|
for row in resp.get_json()['data']:
|
||||||
|
# Lists differ in shape; the asset number is the field all of them
|
||||||
|
# carry, either directly or on a nested asset.
|
||||||
|
found.append(row.get('assetnumber')
|
||||||
|
or (row.get('asset') or {}).get('assetnumber'))
|
||||||
|
return [f for f in found if f]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('listpath,createpath,assettype', LISTS)
|
||||||
|
def test_a_list_search_finds_a_gauge_lab_reference(client, db, auth_headers,
|
||||||
|
listpath, createpath, assettype):
|
||||||
|
assetnumber = f'ZZ{assettype[:4].upper()}01'
|
||||||
|
_seed(client, db, auth_headers, createpath, assettype, assetnumber)
|
||||||
|
assert assetnumber in _numbers(client, auth_headers, listpath,
|
||||||
|
f'ZZG{assetnumber}')
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('listpath,createpath,assettype', LISTS)
|
||||||
|
def test_a_list_search_finds_a_maintenance_reference(client, db, auth_headers,
|
||||||
|
listpath, createpath, assettype):
|
||||||
|
assetnumber = f'ZZ{assettype[:4].upper()}02'
|
||||||
|
_seed(client, db, auth_headers, createpath, assettype, assetnumber)
|
||||||
|
assert assetnumber in _numbers(client, auth_headers, listpath,
|
||||||
|
f'ZZM{assetnumber}')
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('listpath,createpath,assettype', LISTS)
|
||||||
|
def test_a_list_search_still_excludes_a_non_match(client, db, auth_headers,
|
||||||
|
listpath, createpath, assettype):
|
||||||
|
"""Widening the clause must not turn the search box into a pass-through."""
|
||||||
|
assetnumber = f'ZZ{assettype[:4].upper()}03'
|
||||||
|
_seed(client, db, auth_headers, createpath, assettype, assetnumber)
|
||||||
|
assert _numbers(client, auth_headers, listpath, 'ZZNOTHINGMATCHESTHIS') == []
|
||||||
Reference in New Issue
Block a user