Files
shopdb-flask/tests/test_plugins/test_printer_install_batch.py
cproudlock 3eaaee0e50 printers: resolve installer vendor via the model + fix batch download base URL
Two fixes for the printer install-batch on prod data:

1. Vendor was read only from the printer's direct vendorid, which the legacy
   import never sets (it sets the model; legacy resolved vendor through the
   model). Every prod printer came back vendor "unknown", so all fell into the
   manual group and the universal PrinterInstaller.exe block never emitted. Now
   resolve vendor via the model's vendor when the printer has no direct one, as
   the classic installprinter.asp did.

2. Harden the download base URL. Behind IIS the app sees http on a loopback
   port and url_root drops the /shopdb mount, giving a broken download URL when
   site_base_url is unset. Fall back to https + the forwarded Host + script_root.

Test: a printer with no vendorid but an HP/Xerox model now groups universal.
2026-07-29 12:56:31 -04:00

105 lines
4.2 KiB
Python

"""Tests for the printer installer batch endpoint (/api/printers/install-batch).
The printer installer map lets a user pick printers on the shopfloor map and
download a .bat that installs them, grouping the same way the classic
installprinter.asp did (HP/Xerox -> universal PrinterInstaller.exe; other
printers with a .exe installpath -> that installer /SILENT; anything else ->
manual).
"""
import pytest
@pytest.fixture
def printer_assettype(db):
from shopdb.core.models import AssetType
at = AssetType(assettype='printer', pluginname='printers',
tablename='printers', description='Printers')
db.session.add(at)
db.session.commit()
return at
def _vendor(db, name):
from shopdb.core.models import Vendor
v = Vendor(vendor=name)
db.session.add(v)
db.session.commit()
return v
def _make_printer(client, auth_headers, **payload):
resp = client.post('/api/printers', json=payload, headers=auth_headers)
assert resp.status_code == 201, resp.get_json()
return resp.get_json()['data']['printer']['printerid']
def test_install_batch_groups_universal_specific_and_manual(
client, db, auth_headers, printer_assettype):
hp = _vendor(db, 'HP')
zebra = _vendor(db, 'Zebra')
epson = _vendor(db, 'Epson')
# HP -> universal installer
hp_id = _make_printer(client, auth_headers, assetnumber='CSF04-WJRP2035-HP',
hostname='wjprn04', vendorid=hp.vendorid)
# Zebra with a .exe installpath -> specific silent install
zebra_id = _make_printer(client, auth_headers, assetnumber='LABELER-ZEBRA',
hostname='wjprn05', vendorid=zebra.vendorid,
installpath='./installers/printers/zddriver.exe')
# Epson with a .zip installpath -> manual (we do not run a .zip /SILENT)
epson_id = _make_printer(client, auth_headers, assetnumber='RECEIPT-EPSON',
hostname='wjprn06', vendorid=epson.vendorid,
installpath='./installers/printers/c350navi.zip')
ids = '%d,%d,%d' % (hp_id, zebra_id, epson_id)
resp = client.get('/api/printers/install-batch?printerids=' + ids,
headers=auth_headers)
assert resp.status_code == 200
assert 'application/octet-stream' in resp.headers['Content-Type']
assert '.bat' in resp.headers['Content-Disposition']
bat = resp.get_data(as_text=True)
# Universal group: HP printer name in a /PRINTER list + PrinterInstaller.exe
assert 'PrinterInstaller.exe' in bat
assert '/PRINTER="CSF04-WJRP2035-HP"' in bat
# Specific: the .exe installpath resolved + run /SILENT
assert 'installers/printers/zddriver.exe' in bat
assert '/SILENT' in bat
# Manual: the .zip printer is flagged, NOT executed
assert 'MANUAL' in bat
assert 'RECEIPT-EPSON' in bat
assert 'c350navi.zip' not in bat # never handed to the runner
def test_install_batch_resolves_vendor_via_model(
client, db, auth_headers, printer_assettype):
"""A printer with no direct vendorid still groups as universal when its
MODEL's vendor is HP/Xerox (the import sets the model, not the printer's
vendorid) - the bug that dumped every prod printer into 'manual (unknown)'."""
from shopdb.core.models import Vendor, Model
xerox = Vendor(vendor='Xerox')
db.session.add(xerox)
db.session.commit()
model = Model(modelnumber='VersaLink C7125', vendorid=xerox.vendorid)
db.session.add(model)
db.session.commit()
# No vendorid on the printer - only the model ties it to Xerox.
pid = _make_printer(client, auth_headers, assetnumber='SpoolsInspection-Xerox',
hostname='wjprn07', modelnumberid=model.modelnumberid)
resp = client.get('/api/printers/install-batch?printerids=%d' % pid,
headers=auth_headers)
assert resp.status_code == 200
bat = resp.get_data(as_text=True)
assert 'PrinterInstaller.exe' in bat
assert '/PRINTER="SpoolsInspection-Xerox"' in bat
assert 'MANUAL' not in bat
def test_install_batch_requires_ids(client, db, auth_headers, printer_assettype):
resp = client.get('/api/printers/install-batch', headers=auth_headers)
assert resp.status_code == 400