display FQDN keying + kiosk dropdown + dispatcher + multi-word search
This commit is contained in:
@@ -129,7 +129,29 @@ def test_dashboard_role_requires_businessunit(client, db, auth_headers):
|
||||
'ipaddress': '10.20.30.55', 'displayrole': 'dashboard',
|
||||
}, headers=auth_headers)
|
||||
assert resp.status_code == 400
|
||||
assert 'businessunitid' in resp.get_json()['data']['error']['message'].lower()
|
||||
assert 'location' in resp.get_json()['data']['error']['message'].lower()
|
||||
|
||||
|
||||
def test_fqdn_mapping_create_and_resolve(client, db, auth_headers):
|
||||
# A mapping can be keyed by FQDN (no IP), and /display-role resolves it.
|
||||
resp = client.post('/api/dashboarddefaults', json={
|
||||
'fqdn': 'FABC123.device.geaerospace.net', 'displayrole': 'lobby',
|
||||
}, headers=auth_headers)
|
||||
assert resp.status_code == 201, resp.data
|
||||
assert resp.get_json()['data']['fqdn'] == 'fabc123.device.geaerospace.net'
|
||||
|
||||
# resolve by FQDN (case-insensitive)
|
||||
r = client.get('/api/dashboarddefaults/display-role?fqdn=fabc123.device.geaerospace.net')
|
||||
body = r.get_json()['data']
|
||||
assert body['role'] == 'lobby'
|
||||
assert body['path'] == '/tv'
|
||||
|
||||
|
||||
def test_mapping_requires_fqdn_or_ip(client, db, auth_headers):
|
||||
resp = client.post('/api/dashboarddefaults', json={'displayrole': 'lobby'},
|
||||
headers=auth_headers)
|
||||
assert resp.status_code == 400
|
||||
assert 'fqdn or ipaddress' in resp.get_json()['data']['error']['message'].lower()
|
||||
|
||||
|
||||
def test_invalid_role_rejected(client, db, auth_headers):
|
||||
|
||||
45
tests/test_core/test_display_kiosks.py
Normal file
45
tests/test_core/test_display_kiosks.py
Normal file
@@ -0,0 +1,45 @@
|
||||
"""The /computers/display-kiosks picker: reporting displays with a derived FQDN.
|
||||
|
||||
Feeds the Dashboard Defaults kiosk dropdown so an admin picks a display instead
|
||||
of typing an IP. The FQDN is F<serial>.<domain> (device naming), derived from the
|
||||
BIOS serial the collector already reports.
|
||||
"""
|
||||
import pytest
|
||||
|
||||
from shopdb.core.models import AssetType
|
||||
from plugins.computers.models import ComputerType
|
||||
|
||||
KEY = 'testcollectorkey'
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def collector_key(app):
|
||||
old = app.config.get('COLLECTOR_API_KEY')
|
||||
app.config['COLLECTOR_API_KEY'] = KEY
|
||||
yield KEY
|
||||
app.config['COLLECTOR_API_KEY'] = old
|
||||
|
||||
|
||||
def test_display_kiosks_derives_fqdn(client, db, collector_key):
|
||||
db.session.add(AssetType(assettype='computer', pluginname='computers',
|
||||
tablename='computers'))
|
||||
db.session.add(ComputerType(computertype='Kiosk'))
|
||||
db.session.commit()
|
||||
|
||||
# a display reports in via the collector (pctype -> Kiosk type, with serial)
|
||||
resp = client.post('/api/collector/computers', json={
|
||||
'hostname': 'WJDISP01', 'serialnumber': 'ABC1234',
|
||||
'pctype': 'gea-shopfloor-display',
|
||||
}, headers={'X-API-Key': KEY})
|
||||
assert resp.status_code == 200, resp.data
|
||||
|
||||
rows = client.get('/api/computers/display-kiosks').get_json()['data']
|
||||
match = [k for k in rows if k['hostname'] == 'WJDISP01']
|
||||
assert match, rows
|
||||
assert match[0]['fqdn'] == 'fabc1234.device.geaerospace.net'
|
||||
assert match[0]['serialnumber'] == 'ABC1234'
|
||||
|
||||
|
||||
def test_display_kiosks_empty_when_no_kiosk_type(client, db):
|
||||
# No 'Kiosk' ComputerType -> empty list, not an error.
|
||||
assert client.get('/api/computers/display-kiosks').get_json()['data'] == []
|
||||
39
tests/test_core/test_search_multiword.py
Normal file
39
tests/test_core/test_search_multiword.py
Normal file
@@ -0,0 +1,39 @@
|
||||
"""Global search matches multi-word queries by WORD (every word, any order or
|
||||
field), not just the exact contiguous phrase.
|
||||
|
||||
Regression: 'CSF Roles' returned nothing because search did a single
|
||||
ilike('%CSF Roles%'). Now each word must match (ORed across fields), so a record
|
||||
with both words - even reversed or split - is found; a record with only one is
|
||||
not.
|
||||
"""
|
||||
from shopdb.core.models import AssetType, Asset
|
||||
|
||||
|
||||
def _seed(client, db, auth_headers, assetnumber, name):
|
||||
if not AssetType.query.filter_by(assettype='computer').first():
|
||||
db.session.add(AssetType(assettype='computer', pluginname='computer',
|
||||
tablename='computer', description='c'))
|
||||
db.session.commit()
|
||||
r = client.post('/api/computers', json={'assetnumber': assetnumber},
|
||||
headers=auth_headers)
|
||||
assert r.status_code == 201, r.get_json()
|
||||
asset = Asset.query.filter_by(assetnumber=assetnumber).first()
|
||||
asset.name = name
|
||||
db.session.commit()
|
||||
|
||||
|
||||
def _titles(client, auth_headers, term):
|
||||
r = client.get(f'/api/search?q={term}', headers=auth_headers)
|
||||
assert r.status_code == 200, r.get_json()
|
||||
return {h['title'] for h in r.get_json()['data']['results']}
|
||||
|
||||
|
||||
def test_multiword_matches_all_words_any_order(client, db, auth_headers):
|
||||
_seed(client, db, auth_headers, 'MW-1', 'CSF Roles Alpha') # contiguous
|
||||
_seed(client, db, auth_headers, 'MW-2', 'Roles for the CSF Beta') # split/reversed
|
||||
_seed(client, db, auth_headers, 'MW-3', 'CSF only') # one word only
|
||||
|
||||
titles = _titles(client, auth_headers, 'CSF Roles')
|
||||
assert 'CSF Roles Alpha' in titles # exact phrase still works
|
||||
assert 'Roles for the CSF Beta' in titles # words split/reversed now match
|
||||
assert 'CSF only' not in titles # missing a word -> excluded
|
||||
Reference in New Issue
Block a user