178 lines
8.2 KiB
Python
178 lines
8.2 KiB
Python
"""Which driver a printer installs with.
|
|
|
|
One row per model was unworkable: HP and Xerox universal drivers cover 41 of the
|
|
reference site's 44 printers, so binding a driver to a single model meant 21
|
|
near-duplicate rows pointing at one package - a table nobody keeps true, and the
|
|
reason 42 of 44 printers could not resolve a driver at all.
|
|
|
|
The order is most-specific-first, and each step exists for a printer that really
|
|
is on this floor: a plotter and a card printer need their own driver, everything
|
|
else takes its make's universal one.
|
|
"""
|
|
|
|
import pytest
|
|
|
|
from shopdb.core.models import Vendor, Model
|
|
from plugins.printers.models import Printer, PrinterDriver
|
|
from plugins.printers.api.asset_routes import _printer_driver
|
|
|
|
|
|
def _universal():
|
|
return (PrinterDriver.query
|
|
.filter(PrinterDriver.modelnumberid.is_(None),
|
|
PrinterDriver.isactive == True)
|
|
.order_by(PrinterDriver.name).all())
|
|
|
|
|
|
@pytest.fixture
|
|
def fleet(db):
|
|
hp = Vendor(vendor='HP')
|
|
xerox = Vendor(vendor='Xerox')
|
|
db.session.add_all([hp, xerox])
|
|
db.session.flush()
|
|
|
|
laserjet = Model(modelnumber='LaserJet M602', vendorid=hp.vendorid)
|
|
designjet = Model(modelnumber='DesignJet T1700', vendorid=hp.vendorid)
|
|
db.session.add_all([laserjet, designjet])
|
|
db.session.flush()
|
|
|
|
upd = PrinterDriver(name='HP Universal Print Driver', drivername='HP Universal Printing PS',
|
|
location=r'\\server\share\hp_upd', vendorid=hp.vendorid, isactive=True)
|
|
plotter = PrinterDriver(name='HP DesignJet T1700', drivername='HP DesignJet T1700dr V4',
|
|
location=r'\\server\share\designjet', vendorid=hp.vendorid,
|
|
modelnumberid=designjet.modelnumberid, isactive=True)
|
|
gpd = PrinterDriver(name='Xerox Global Print Driver PCL6',
|
|
drivername='Xerox Global Print Driver PCL6',
|
|
location=r'\\server\share\xerox', vendorid=xerox.vendorid, isactive=True)
|
|
db.session.add_all([upd, plotter, gpd])
|
|
db.session.commit()
|
|
return {'hp': hp, 'xerox': xerox, 'laserjet': laserjet, 'designjet': designjet,
|
|
'upd': upd, 'plotter': plotter, 'gpd': gpd}
|
|
|
|
|
|
def test_a_printer_takes_its_makes_universal_driver(fleet):
|
|
"""The case that covers most of a floor: no per-model row exists, and none
|
|
should have to."""
|
|
printer = Printer(vendorid=fleet['hp'].vendorid, modelnumberid=fleet['laserjet'].modelnumberid)
|
|
assert _printer_driver(printer, _universal()).name == 'HP Universal Print Driver'
|
|
|
|
|
|
def test_a_model_specific_driver_beats_the_universal_one(fleet):
|
|
"""A plotter is not a LaserJet. If the universal driver won here, the
|
|
DesignJet would be installed with a driver that cannot drive it."""
|
|
printer = Printer(vendorid=fleet['hp'].vendorid, modelnumberid=fleet['designjet'].modelnumberid)
|
|
assert _printer_driver(printer, _universal()).name == 'HP DesignJet T1700'
|
|
|
|
|
|
def test_vendors_do_not_bleed_into_each_other(fleet):
|
|
"""A Xerox must never resolve to the HP driver, whatever the ordering."""
|
|
printer = Printer(vendorid=fleet['xerox'].vendorid, modelnumberid=None)
|
|
assert _printer_driver(printer, _universal()).name == 'Xerox Global Print Driver PCL6'
|
|
|
|
|
|
def test_a_printer_with_no_vendor_resolves_to_nothing(fleet):
|
|
"""Better nothing than a guess: installing the wrong driver is worse than
|
|
reporting that a printer has none."""
|
|
printer = Printer(vendorid=None, modelnumberid=None)
|
|
assert _printer_driver(printer, _universal()) is None
|
|
|
|
|
|
def test_a_make_with_no_driver_row_resolves_to_nothing(db, fleet):
|
|
"""A vendor nobody has added a driver for is unresolved, not misresolved."""
|
|
zebra = Vendor(vendor='Zebra')
|
|
db.session.add(zebra)
|
|
db.session.commit()
|
|
printer = Printer(vendorid=zebra.vendorid, modelnumberid=None)
|
|
assert _printer_driver(printer, _universal()) is None
|
|
|
|
|
|
def test_the_pre_vendorid_naming_convention_still_resolves(db, fleet):
|
|
"""A site that populated printerdrivers before the column existed matched on
|
|
the vendor word in the driver's NAME. That must keep working, or an upgrade
|
|
silently takes every driver away."""
|
|
epson = Vendor(vendor='Epson')
|
|
db.session.add(epson)
|
|
db.session.flush()
|
|
db.session.add(PrinterDriver(name='Epson ColorWorks universal', drivername='EPSON TM-C3500',
|
|
location=r'\\server\share\epson', isactive=True))
|
|
db.session.commit()
|
|
# vendor attached, not just vendorid: the legacy path reads the vendor's
|
|
# NAME, which only exists through the relationship.
|
|
printer = Printer(vendorid=epson.vendorid, modelnumberid=None)
|
|
printer.vendor = epson
|
|
assert _printer_driver(printer, _universal()).name == 'Epson ColorWorks universal'
|
|
|
|
|
|
def test_a_row_that_names_a_vendor_is_not_matched_by_its_text(db, fleet):
|
|
"""A driver whose vendorid is set and does NOT match must not then be picked
|
|
up by the name convention: a mis-set vendor would resolve to the wrong
|
|
package, which is worse than resolving to none."""
|
|
brother = Vendor(vendor='Brother')
|
|
db.session.add(brother)
|
|
db.session.flush()
|
|
# Named for Brother, but bound to HP by id - the id is the truth.
|
|
db.session.add(PrinterDriver(name='Brother universal', drivername='Brother Universal',
|
|
location=r'\\server\share\brother',
|
|
vendorid=fleet['hp'].vendorid, isactive=True))
|
|
db.session.commit()
|
|
printer = Printer(vendorid=brother.vendorid, modelnumberid=None)
|
|
printer.vendor = brother
|
|
assert _printer_driver(printer, _universal()) is None
|
|
|
|
|
|
# --- the two fields the converger actually needs -----------------------------
|
|
#
|
|
# drivername is the exact string the INF declares, and it is what
|
|
# Add-PrinterDriver matches on - `name` is ours to choose and means nothing to
|
|
# Windows. vendorid attaches a universal driver (HP UPD, Xerox GPD) to a whole
|
|
# make. Neither was read from the request body, so both came back null on a
|
|
# 201, and there was no interface that could set them: the shipped converger
|
|
# had nothing to match and installed nothing, and driver-name drift could never
|
|
# be detected because the expected value was never stored.
|
|
|
|
def test_a_driver_keeps_the_inf_name_and_vendor_it_was_given(client, db,
|
|
auth_headers):
|
|
from plugins.printers.models import PrinterDriver
|
|
|
|
created = client.post('/api/printers/drivers', headers=auth_headers, json={
|
|
'name': 'HP universal',
|
|
'location': r'\\server\share\hpupd',
|
|
'drivername': 'HP Universal Printing PCL 6',
|
|
'vendorid': 1,
|
|
})
|
|
assert created.status_code == 201, created.get_json()
|
|
body = created.get_json()['data']
|
|
assert body['drivername'] == 'HP Universal Printing PCL 6'
|
|
assert body['vendorid'] == 1
|
|
|
|
stored = db.session.get(PrinterDriver, body['driverid'])
|
|
assert stored.drivername == 'HP Universal Printing PCL 6'
|
|
assert stored.vendorid == 1
|
|
|
|
|
|
def test_the_inf_name_and_vendor_can_be_changed_afterwards(client, db,
|
|
auth_headers):
|
|
created = client.post('/api/printers/drivers', headers=auth_headers, json={
|
|
'name': 'Xerox universal', 'location': r'\\server\share\xerox'})
|
|
driverid = created.get_json()['data']['driverid']
|
|
assert created.get_json()['data']['drivername'] is None
|
|
|
|
updated = client.put('/api/printers/drivers/%d' % driverid,
|
|
headers=auth_headers,
|
|
json={'drivername': 'Xerox Global Print Driver PCL6',
|
|
'vendorid': 2})
|
|
assert updated.status_code == 200, updated.get_json()
|
|
assert updated.get_json()['data']['drivername'] == \
|
|
'Xerox Global Print Driver PCL6'
|
|
assert updated.get_json()['data']['vendorid'] == 2
|
|
|
|
|
|
def test_a_blank_inf_name_clears_it_rather_than_storing_whitespace(
|
|
client, db, auth_headers):
|
|
"""An empty box means "not known", which the converger reads as "cannot
|
|
install this". A whitespace string would look set and match nothing."""
|
|
created = client.post('/api/printers/drivers', headers=auth_headers, json={
|
|
'name': 'Blank test', 'location': r'\\server\share\blank',
|
|
'drivername': ' '})
|
|
assert created.get_json()['data']['drivername'] is None
|