"""Unit tests for script_generator.py — SCRPT-01, SCRPT-02, SCRPT-03, SCRPT-04, SCRPT-05.""" import pytest from imptune.generators.script_generator import render_detect, render_install, render_uninstall def _create_test_driver_and_printer(): """Helper: create a Driver + Printer for integration tests.""" from imptune.db.models import Driver, Printer driver = Driver.create( sha256="abc123", original_filename="test.zip", size_bytes=100, driver_desc='["Test Driver"]', inf_filename="test.inf", ) printer = Printer.create( name="Test Printer", ip_address="10.0.0.1", port_name="IP_10.0.0.1", driver=driver, duplex_mode="LongEdge", color_mode=True, paper_size="A4", collate=True, ) return driver, printer SAMPLE_ARGS = dict( printer_name="HP LaserJet 4000", ip_address="192.168.1.10", port_name="IP_192.168.1.10", driver_name="HP Universal Printing PCL 6", inf_filename="hpcu270u.inf", duplex_mode="LongEdge", color_mode=True, paper_size="A4", collate=True, ) def test_render_install_returns_string(): """render_install returns a non-empty string.""" result = render_install(**SAMPLE_ARGS) assert isinstance(result, str) assert len(result) > 0 def test_render_install_contains_pnputil(): """SCRPT-01: Output contains pnputil /add-driver and Add-PrinterDriver.""" result = render_install(**SAMPLE_ARGS) assert "pnputil.exe /add-driver" in result assert "Add-PrinterDriver" in result assert "hpcu270u.inf" in result assert "HP Universal Printing PCL 6" in result def test_render_install_print_config(): """SCRPT-01: Set-PrintConfiguration with translated duplex mode.""" # LongEdge -> TwoSidedLongEdge result = render_install(**SAMPLE_ARGS) assert "Set-PrintConfiguration" in result assert "TwoSidedLongEdge" in result assert "A4" in result # ShortEdge -> TwoSidedShortEdge result_short = render_install(**{**SAMPLE_ARGS, "duplex_mode": "ShortEdge"}) assert "TwoSidedShortEdge" in result_short # OneSided -> OneSided (no change) result_one = render_install(**{**SAMPLE_ARGS, "duplex_mode": "OneSided"}) assert "OneSided" in result_one # Must NOT contain the two-sided variants when OneSided assert "TwoSided" not in result_one def test_render_install_wow64_guard(): """SCRPT-05: WOW64 relaunch guard is present in the output.""" result = render_install(**SAMPLE_ARGS) assert "PROCESSOR_ARCHITECTURE" in result assert "SysNative" in result # Guard must appear near the top (before pnputil) wow64_pos = result.find("PROCESSOR_ARCHITECTURE") pnputil_pos = result.find("pnputil.exe") assert wow64_pos < pnputil_pos, "WOW64 guard must appear before pnputil" def test_render_install_uac_guard(): """SCRPT-04: SYSTEM vs user detection with UAC self-elevation.""" result = render_install(**SAMPLE_ARGS) assert "IsSystem" in result assert "Start-Process" in result assert "-Verb Runas" in result or "Verb Runas" in result def test_render_install_idempotency(): """SCRPT-01: All add operations wrapped in idempotency checks.""" result = render_install(**SAMPLE_ARGS) # Port idempotency assert "Get-PrinterPort" in result assert "Add-PrinterPort" in result # Printer idempotency assert "Get-Printer" in result assert "Add-Printer" in result # Port check must come before Add-PrinterPort get_port_pos = result.find("Get-PrinterPort") add_port_pos = result.find("Add-PrinterPort") assert get_port_pos < add_port_pos, "Get-PrinterPort check must precede Add-PrinterPort" def test_render_install_booleans(): """Color and collate are rendered as $true / $false in the script.""" result_true = render_install(**SAMPLE_ARGS) # color_mode=True, collate=True assert "$true" in result_true result_false = render_install(**{**SAMPLE_ARGS, "color_mode": False, "collate": False}) assert "$false" in result_false def test_render_uninstall(): """SCRPT-02: render_uninstall produces correct removal order with SilentlyContinue.""" result = render_uninstall("Test Printer", "HP Driver", "IP_10.0.0.1") # All three Remove-* commands must be present assert 'Remove-Printer -Name "Test Printer"' in result assert 'Remove-PrinterDriver -Name "HP Driver"' in result assert 'Remove-PrinterPort -Name "IP_10.0.0.1"' in result # All must have -ErrorAction SilentlyContinue assert result.count("-ErrorAction SilentlyContinue") >= 3 # Order: Remove-Printer BEFORE Remove-PrinterDriver (driver removal fails if printer still active) printer_pos = result.find("Remove-Printer -Name") driver_pos = result.find("Remove-PrinterDriver -Name") port_pos = result.find("Remove-PrinterPort -Name") assert printer_pos < driver_pos, "Remove-Printer must appear before Remove-PrinterDriver" assert driver_pos < port_pos, "Remove-PrinterDriver must appear before Remove-PrinterPort" def test_render_detect(): """SCRPT-03: render_detect follows Intune detection contract (Write-Output + exit 0/1).""" result = render_detect("Test Printer") assert 'Get-Printer -Name "Test Printer"' in result assert "Write-Output" in result assert "exit 0" in result assert "exit 1" in result # --------------------------------------------------------------------------- # Integration tests — script API endpoints # --------------------------------------------------------------------------- def test_install_endpoint(client): """GET /printers/{id}/scripts/install returns 200 with pnputil in content.""" _driver, printer = _create_test_driver_and_printer() response = client.get(f"/printers/{printer.id}/scripts/install") assert response.status_code == 200 assert "pnputil" in response.text def test_uninstall_endpoint(client): """GET /printers/{id}/scripts/uninstall returns 200 with Remove-Printer in content.""" _driver, printer = _create_test_driver_and_printer() response = client.get(f"/printers/{printer.id}/scripts/uninstall") assert response.status_code == 200 assert "Remove-Printer" in response.text def test_detect_endpoint(client): """GET /printers/{id}/scripts/detect returns 200 with Write-Output in content.""" _driver, printer = _create_test_driver_and_printer() response = client.get(f"/printers/{printer.id}/scripts/detect") assert response.status_code == 200 assert "Write-Output" in response.text def test_script_endpoint_missing_printer(client): """GET /printers/{id}/scripts/install returns 404 for nonexistent printer.""" response = client.get("/printers/9999/scripts/install") assert response.status_code == 404 def test_script_endpoint_no_driver(client): """GET /printers/{id}/scripts/install returns 422 when no driver assigned.""" from imptune.db.models import Printer printer = Printer.create( name="No Driver Printer", ip_address="10.0.0.2", port_name="IP_10.0.0.2", driver=None, duplex_mode="OneSided", color_mode=True, paper_size="A4", collate=True, ) response = client.get(f"/printers/{printer.id}/scripts/install") assert response.status_code == 422