"""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