diff --git a/tests/test_printer_crud.py b/tests/test_printer_crud.py new file mode 100644 index 0000000..20044bd --- /dev/null +++ b/tests/test_printer_crud.py @@ -0,0 +1,207 @@ +"""Integration tests for printer and client CRUD endpoints.""" +import pytest +from fastapi.testclient import TestClient + + +# --------------------------------------------------------------------------- +# Task 1: RED state — routes do not exist yet, tests should fail +# --------------------------------------------------------------------------- + + +def test_create_printer_persisted(client: TestClient) -> None: + """POST /printers with required fields returns 200; GET /printers contains printer name.""" + from imptune.db.models import Printer + + resp = client.post( + "/printers", + data={ + "name": "Test Printer", + "ip_address": "192.168.1.100", + "port_name": "IP_192_168_1_100", + }, + ) + assert resp.status_code == 200 + + # GET /printers page contains the printer name + page = client.get("/printers") + assert page.status_code == 200 + assert "Test Printer" in page.text + + # Verify DB persistence + count = Printer.select().where(Printer.name == "Test Printer").count() + assert count == 1 + + +def test_create_printer_duplex(client: TestClient) -> None: + """POST /printers with duplex_mode=LongEdge persists correctly.""" + from imptune.db.models import Printer + + resp = client.post( + "/printers", + data={ + "name": "Duplex Printer", + "ip_address": "192.168.1.101", + "port_name": "IP_192_168_1_101", + "duplex_mode": "LongEdge", + }, + ) + assert resp.status_code == 200 + + printer = Printer.get(Printer.name == "Duplex Printer") + assert printer.duplex_mode == "LongEdge" + + +def test_create_printer_color_mode(client: TestClient) -> None: + """POST /printers with color_mode not sent (unchecked) sets color_mode=False.""" + from imptune.db.models import Printer + + resp = client.post( + "/printers", + data={ + "name": "Mono Printer", + "ip_address": "192.168.1.102", + "port_name": "IP_192_168_1_102", + # color_mode intentionally omitted (unchecked checkbox) + }, + ) + assert resp.status_code == 200 + + printer = Printer.get(Printer.name == "Mono Printer") + assert printer.color_mode is False + + +def test_create_printer_paper_size(client: TestClient) -> None: + """POST /printers with paper_size=Letter persists correctly.""" + from imptune.db.models import Printer + + resp = client.post( + "/printers", + data={ + "name": "Letter Printer", + "ip_address": "192.168.1.103", + "port_name": "IP_192_168_1_103", + "paper_size": "Letter", + }, + ) + assert resp.status_code == 200 + + printer = Printer.get(Printer.name == "Letter Printer") + assert printer.paper_size == "Letter" + + +def test_create_printer_collate(client: TestClient) -> None: + """POST /printers with collate not sent (unchecked) sets collate=False.""" + from imptune.db.models import Printer + + resp = client.post( + "/printers", + data={ + "name": "No Collate Printer", + "ip_address": "192.168.1.104", + "port_name": "IP_192_168_1_104", + # collate intentionally omitted (unchecked checkbox) + }, + ) + assert resp.status_code == 200 + + printer = Printer.get(Printer.name == "No Collate Printer") + assert printer.collate is False + + +def test_create_client(client: TestClient) -> None: + """POST /clients with name=Contoso returns 200; GET /clients contains Contoso.""" + resp = client.post("/clients", data={"name": "Contoso"}) + assert resp.status_code == 200 + + page = client.get("/clients") + assert page.status_code == 200 + assert "Contoso" in page.text + + +def test_printer_grouped_by_client(client: TestClient) -> None: + """Printer assigned to a client appears under that client group heading.""" + from imptune.db.models import Client, Printer + + # Create client + resp = client.post("/clients", data={"name": "Contoso"}) + assert resp.status_code == 200 + + contoso = Client.get(Client.name == "Contoso") + + # Create printer assigned to that client + resp = client.post( + "/printers", + data={ + "name": "Contoso Printer", + "ip_address": "10.0.0.1", + "port_name": "IP_10_0_0_1", + "client_id": str(contoso.id), + }, + ) + assert resp.status_code == 200 + + # GET /printers should show "Contoso" as a group header + page = client.get("/printers") + assert page.status_code == 200 + html = page.text + assert "Contoso" in html + # Client name should appear in a heading element + assert " None: + """POST /printers with empty name returns 400.""" + resp = client.post( + "/printers", + data={ + "name": "", + "ip_address": "192.168.1.100", + "port_name": "IP_192_168_1_100", + }, + ) + assert resp.status_code == 400 + + +def test_create_printer_invalid_ip(client: TestClient) -> None: + """POST /printers with empty ip_address returns 400.""" + resp = client.post( + "/printers", + data={ + "name": "Valid Name", + "ip_address": "", + "port_name": "SOME_PORT", + }, + ) + assert resp.status_code == 400 + + +def test_delete_printer(client: TestClient) -> None: + """DELETE /printers/{id} removes the printer; GET /printers no longer shows it.""" + from imptune.db.models import Printer + + # Create a printer + resp = client.post( + "/printers", + data={ + "name": "To Delete", + "ip_address": "192.168.1.200", + "port_name": "IP_192_168_1_200", + }, + ) + assert resp.status_code == 200 + + # Find its ID + printer = Printer.get(Printer.name == "To Delete") + printer_id = printer.id + + # Delete it + resp = client.delete(f"/printers/{printer_id}") + assert resp.status_code == 200 + + # Confirm it's gone from the DB + count = Printer.select().where(Printer.id == printer_id).count() + assert count == 0 + + # GET /printers should no longer show it + page = client.get("/printers") + assert "To Delete" not in page.text