import asyncio
import xml.etree.ElementTree as ET
import pytest
from fastapi import HTTPException
from starlette.requests import Request
from app.modules.hardware.labels import hardware_label_url, hardware_label_qr
from app.modules.hardware.frontend import views
def test_label_links_to_exact_asset():
assert hardware_label_url('https://hub.example.dk/', 42) == 'https://hub.example.dk/hardware/42'
assert hardware_label_url('http://192.168.1.10:8001', 42) == 'http://192.168.1.10:8001/hardware/42'
@pytest.mark.parametrize('url', ['javascript:alert(1)', 'https://user:secret@hub.dk', 'https://hub.dk?token=secret', 'https://hub.dk/#secret', ''])
def test_invalid_label_url_is_rejected(url):
with pytest.raises(HTTPException):
hardware_label_url(url, 1)
def test_qr_is_a_local_vector_with_quiet_zone():
xml = ET.fromstring(hardware_label_qr('https://hub.example.dk/hardware/42'))
assert xml.tag == '{http://www.w3.org/2000/svg}svg'
assert xml.find('{http://www.w3.org/2000/svg}path') is not None
assert 'http' not in xml.find('{http://www.w3.org/2000/svg}path').attrib['d']
def test_label_route_renders_asset_and_escapes_text(monkeypatch):
monkeypatch.setattr(views, 'execute_query', lambda sql, params: [{'id':42, 'brand':'BMC', 'model':'', 'serial_number':'ABC-123'}])
request = Request({'type':'http','method':'GET','path':'/hardware/42/label','headers':[],'scheme':'http','server':('localhost',8001),'query_string':b''})
response = asyncio.run(views.hardware_label(request,42,size='62x40',base_url='https://hub.example.dk'))
body=response.body.decode()
assert 'BMC-00042' in body
assert 'https://hub.example.dk/hardware/42' in body
assert '' not in body
assert '<script>bad</script>' in body
assert 'size:62mm 40mm' in body
assert response.headers['cache-control']=='no-store'
def test_missing_asset_and_invalid_size(monkeypatch):
monkeypatch.setattr(views,'execute_query',lambda *args: [])
with pytest.raises(HTTPException) as error:
asyncio.run(views.hardware_label(None,42,size='62x40',base_url='https://hub.example.dk'))
assert error.value.status_code==404
with pytest.raises(HTTPException) as error:
asyncio.run(views.hardware_label(None,42,size='bad',base_url='https://hub.example.dk'))
assert error.value.status_code==400