From d3590017e924047ff77929727f3d92f22ea19483 Mon Sep 17 00:00:00 2001 From: Kawa Date: Mon, 13 Apr 2026 10:47:09 +0200 Subject: [PATCH] test(09-03): add failing .ps1 route and detail-page link tests - Create tests/test_script_download.py with 5 tests for .ps1 routes (install/uninstall/detect, 404, 422) - Add test_detail_page_shows_script_links to TestCommandPreview in tests/test_packages.py - All 6 new tests go RED (routes and template links do not exist yet) --- tests/test_packages.py | 10 +++ tests/test_script_download.py | 120 ++++++++++++++++++++++++++++++++++ 2 files changed, 130 insertions(+) create mode 100644 tests/test_script_download.py diff --git a/tests/test_packages.py b/tests/test_packages.py index 6a39f1c..0c53125 100644 --- a/tests/test_packages.py +++ b/tests/test_packages.py @@ -190,6 +190,16 @@ class TestCommandPreview: assert f"/printers/{printer.id}/icon" in html assert "icon-status" in html + def test_detail_page_shows_script_links(self, client, setup_printer_with_driver): + """Printer detail page shows 3 direct .ps1 script download links when driver assigned.""" + printer, _ = setup_printer_with_driver + resp = client.get(f"/printers/{printer.id}") + assert resp.status_code == 200 + html = resp.text + assert f"/printers/{printer.id}/scripts/install.ps1" in html + assert f"/printers/{printer.id}/scripts/uninstall.ps1" in html + assert f"/printers/{printer.id}/scripts/detect.ps1" in html + # --------------------------------------------------------------------------- # Icon inclusion in .intunewin export diff --git a/tests/test_script_download.py b/tests/test_script_download.py new file mode 100644 index 0000000..0fb5aec --- /dev/null +++ b/tests/test_script_download.py @@ -0,0 +1,120 @@ +"""Integration tests for the .ps1-suffixed script download routes.""" +import io +import json +import zipfile + +import pytest + + +# --------------------------------------------------------------------------- +# Fixtures (same pattern as tests/test_packages.py) +# --------------------------------------------------------------------------- + + +@pytest.fixture +def driver_zip_bytes(): + """Create a minimal valid driver ZIP with a fake INF and CAT file.""" + buf = io.BytesIO() + with zipfile.ZipFile(buf, "w", compression=zipfile.ZIP_DEFLATED) as zf: + zf.writestr("printer.inf", "[Version]\nSignature=$WINDOWS NT$\n") + zf.writestr("printer.cat", "FAKE_CAT") + return buf.getvalue() + + +@pytest.fixture +def setup_printer_with_driver(tmp_data_dir, driver_zip_bytes): + """Create Driver record (with ZIP on disk) and Printer record linked to it.""" + import hashlib + import os + + import imptune.config as cfg + from imptune.db.models import Driver, Printer + + sha = hashlib.sha256(driver_zip_bytes).hexdigest() + drivers_dir = cfg.DRIVERS_DIR + os.makedirs(drivers_dir, exist_ok=True) + zip_path = os.path.join(drivers_dir, f"{sha}.zip") + with open(zip_path, "wb") as f: + f.write(driver_zip_bytes) + + driver = Driver.create( + sha256=sha, + original_filename="printer_driver.zip", + size_bytes=len(driver_zip_bytes), + driver_desc=json.dumps(["HP LaserJet Pro"]), + inf_filename="printer.inf", + ) + printer = Printer.create( + name="Test Printer", + ip_address="192.168.1.100", + port_name="IP_192.168.1.100", + driver=driver, + duplex_mode="OneSided", + color_mode=True, + paper_size="A4", + collate=True, + ) + return printer, driver + + +@pytest.fixture +def printer_no_driver(tmp_data_dir): + """Create Printer record with no driver assigned.""" + from imptune.db.models import Printer + + return Printer.create( + name="No Driver Printer", + ip_address="10.0.0.1", + port_name="IP_10.0.0.1", + driver=None, + ) + + +# --------------------------------------------------------------------------- +# .ps1 route tests +# --------------------------------------------------------------------------- + + +class TestPs1Routes: + def test_install_ps1_route(self, client, setup_printer_with_driver): + """GET /printers/{id}/scripts/install.ps1 returns 200 with attachment and PowerShell content.""" + printer, _ = setup_printer_with_driver + resp = client.get(f"/printers/{printer.id}/scripts/install.ps1") + assert resp.status_code == 200 + assert 'attachment' in resp.headers["content-disposition"] + assert 'filename="install.ps1"' in resp.headers["content-disposition"] + body = resp.text + assert len(body) > 0 + assert "Add-Printer" in body or "$PSScriptRoot" in body + + def test_uninstall_ps1_route(self, client, setup_printer_with_driver): + """GET /printers/{id}/scripts/uninstall.ps1 returns 200 with attachment and uninstall content.""" + printer, _ = setup_printer_with_driver + resp = client.get(f"/printers/{printer.id}/scripts/uninstall.ps1") + assert resp.status_code == 200 + assert 'attachment' in resp.headers["content-disposition"] + assert 'filename="uninstall.ps1"' in resp.headers["content-disposition"] + body = resp.text + assert len(body) > 0 + assert "Remove-Printer" in body + + def test_detect_ps1_route(self, client, setup_printer_with_driver): + """GET /printers/{id}/scripts/detect.ps1 returns 200 with attachment and detect content.""" + printer, _ = setup_printer_with_driver + resp = client.get(f"/printers/{printer.id}/scripts/detect.ps1") + assert resp.status_code == 200 + assert 'attachment' in resp.headers["content-disposition"] + assert 'filename="detect.ps1"' in resp.headers["content-disposition"] + body = resp.text + assert len(body) > 0 + assert "Get-Printer" in body + + def test_ps1_routes_missing_printer(self, client, tmp_data_dir): + """GET for non-existent printer returns 404.""" + resp = client.get("/printers/99999/scripts/install.ps1") + assert resp.status_code == 404 + + def test_ps1_routes_no_driver(self, client, printer_no_driver): + """GET for printer without driver returns 422.""" + resp = client.get(f"/printers/{printer_no_driver.id}/scripts/install.ps1") + assert resp.status_code == 422