Files
vergabe-teilnahme/vergabe_teilnahme/tests/test_e2e.py
tegwick 5a231223c0 feat(WP-0012): Querschnitt — Freigaben, Felder, Feedback, Suche, Tests
Implements all 8 tasks of the final cross-cutting workplan:

- T01: Generisches Freigabe-Modal (freigabe_modal, freigabe_erteilen views + templates)
- T02: Freigaben-Übersicht pro Ausschreibung (freigaben_uebersicht view + template)
- T03: EntityFieldConfig Admin-Interface (/felder/<entity_type>/ with HTMX toggle)
- T04: CustomAttribute-Panel (full CRUD with sort, lazy HTMX load)
- T05: Feedback-Backlog mit Statusverwaltung + feedback_success.html template
- T06: End-to-End-Tests in vergabe_teilnahme/tests/test_e2e.py (8 tests)
- T07: Globale Suche erweitert (Dokumente, Nachweise, Referenzen, Marktbegleiter)
- T08: Alle Migrationen sauber, 68/68 Tests grün, Ruff-Fehler in neuem Code behoben

Bugfix: URL-Namespace-Fehler in Abgabe-Templates (ausschreibungen:nachbetrachtung:abgabe → ausschreibungen:abgabe)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-11 17:54:38 +02:00

122 lines
4.8 KiB
Python

import pytest
from django.contrib.contenttypes.models import ContentType
from vergabe_teilnahme.apps.accounts.models import Mitarbeiter
from vergabe_teilnahme.apps.ausschreibungen.models import Ausschreibung
from vergabe_teilnahme.apps.core.models import CustomAttribute, EntityFieldConfig, Freigabe
from vergabe_teilnahme.apps.lose.models import Los
from vergabe_teilnahme.apps.partner.models import Subunternehmer
@pytest.fixture
def mitarbeiter(db):
return Mitarbeiter.objects.create_user(username='testuser', password='x')
@pytest.mark.django_db
class TestVollstaendigerBieterprozess:
def test_ausschreibung_anlegen_bis_freigabe(self, client, mitarbeiter):
client.force_login(mitarbeiter)
# 1. Ausschreibung anlegen
r = client.post('/ausschreibungen/neu/', {
'titel': 'E2E Test Ausschreibung',
'ausschreiber': 'Testamt',
})
assert r.status_code == 302
a = Ausschreibung.objects.get(titel='E2E Test Ausschreibung')
# 2. Los anlegen
r = client.post(f'/ausschreibungen/{a.pk}/lose/neu/', {
'losnummer': '1',
'lostitel': 'Hauptlos',
})
assert r.status_code == 302
assert Los.objects.filter(ausschreibung=a).count() == 1
# 3. Freigabe erteilen via API
ct = ContentType.objects.get_for_model(a)
r = client.post('/freigaben/erteilen/', {
'content_type_id': ct.pk,
'object_id': a.pk,
'freigabe_typ': 'teilnahme',
})
assert r.status_code == 200
assert Freigabe.objects.filter(
content_type=ct, object_id=a.pk, freigabe_typ='teilnahme'
).exists()
# 4. Freigaben-Übersicht abrufbar
r = client.get(f'/ausschreibungen/{a.pk}/freigaben/')
assert r.status_code == 200
assert 'teilnahme' in r.content.decode().lower()
def test_freigabe_modal_liefert_fragment(self, client, mitarbeiter):
client.force_login(mitarbeiter)
a = Ausschreibung.objects.create(titel='Modal Test', ausschreiber='X', status=1)
ct = ContentType.objects.get_for_model(a)
r = client.get(f'/freigaben/modal/?ct={ct.pk}&oid={a.pk}&typ=preis')
assert r.status_code == 200
content = r.content.decode()
assert 'freigabe_typ' in content.lower() or 'freigabe' in content.lower()
def test_abgabe_dokumentieren(self, client, mitarbeiter):
client.force_login(mitarbeiter)
a = Ausschreibung.objects.create(titel='Abgabe Test', ausschreiber='X', status=6)
r = client.post(f'/ausschreibungen/{a.pk}/abgabe/dokumentieren/', {
'abgabe_zeitpunkt': '2026-05-11T12:00',
'abgabe_plattform': 'Vergabeplattform',
})
assert r.status_code == 302
a.refresh_from_db()
assert a.status == 9
@pytest.mark.django_db
class TestFlexibleFelder:
def test_feld_ausblenden_wirkt_im_template(self, client, mitarbeiter):
sub = Subunternehmer.objects.create(name='Test GmbH')
EntityFieldConfig.objects.create(
entity_type='subunternehmer', field_name='webseite', is_hidden=True
)
client.force_login(mitarbeiter)
hidden_fields = sub.get_hidden_fields()
assert 'webseite' in hidden_fields
def test_custom_attribute_hinzufuegen(self, client, mitarbeiter):
sub = Subunternehmer.objects.create(name='Test GmbH')
ct = ContentType.objects.get_for_model(sub)
client.force_login(mitarbeiter)
r = client.post(f'/core/attrs/{ct.pk}/{sub.pk}/neu/', {
'label': 'Vertragsnummer',
'value': 'VN-2026-001',
'data_type': 'text',
})
assert r.status_code == 200
assert CustomAttribute.objects.filter(
content_type=ct, object_id=sub.pk, label='Vertragsnummer'
).exists()
def test_custom_attribute_panel_zeigt_attribute(self, client, mitarbeiter):
sub = Subunternehmer.objects.create(name='Panel Test GmbH')
ct = ContentType.objects.get_for_model(sub)
CustomAttribute.objects.create(
content_type=ct, object_id=sub.pk,
key='kundennr', label='Kundennummer', value='KD-999', data_type='text'
)
client.force_login(mitarbeiter)
r = client.get(f'/core/attrs/{ct.pk}/{sub.pk}/')
assert r.status_code == 200
assert b'Kundennummer' in r.content
def test_feld_konfiguration_seite_erreichbar(self, client, mitarbeiter):
client.force_login(mitarbeiter)
r = client.get('/felder/ausschreibung/')
assert r.status_code == 200
assert b'titel' in r.content
def test_feedback_backlog_erreichbar(self, client, mitarbeiter):
client.force_login(mitarbeiter)
r = client.get('/feedback/backlog/')
assert r.status_code == 200