diff --git a/Test Suite-DE.md b/Test Suite-DE.md index 7d2ac46..386bb52 100644 --- a/Test Suite-DE.md +++ b/Test Suite-DE.md @@ -182,6 +182,21 @@ Die dokumente App enthält 98 Tests und ist damit die umfassendste Test-Suite, d - **test_standard_history_view**: Testet die Standard-Detail-View mit historischem check_date-Parameter - **test_standard_checkliste_view**: Testet die Funktionalität der Checklisten-View +### JSON-Export-Tests + +#### JSONExportManagementCommandTest +- **test_export_json_command_to_file**: Testet, dass der export_json-Befehl JSON in die angegebene Datei ausgibt +- **test_export_json_command_stdout**: Testet, dass der export_json-Befehl JSON an stdout ausgibt, wenn keine Datei angegeben ist +- **test_export_json_command_inactive_documents**: Testet, dass der export_json-Befehl inaktive Dokumente herausfiltert +- **test_export_json_command_empty_database**: Testet, dass der export_json-Befehl leere Datenbank angemessen behandelt + +#### StandardJSONViewTest +- **test_standard_json_view_success**: Testet, dass die standard_json-View korrektes JSON für existierendes Dokument zurückgibt +- **test_standard_json_view_not_found**: Testet, dass die standard_json-View 404 für nicht existierendes Dokument zurückgibt +- **test_standard_json_view_json_formatting**: Testet, dass die standard_json-View korrekt formatiertes JSON zurückgibt +- **test_standard_json_view_null_dates**: Testet, dass die standard_json-View null-Datumfelder korrekt behandelt +- **test_standard_json_view_empty_sections**: Testet, dass die standard_json-View leere Dokumentabschnitte behandelt + ### Unvollständige Vorgaben Tests #### IncompleteVorgabenTest @@ -317,9 +332,9 @@ Die stichworte App enthält 18 Tests, die Schlüsselwortmodelle und ihre Sortier ## Test-Statistiken -- **Gesamt-Tests**: 188 +- **Gesamt-Tests**: 206 - **abschnitte**: 32 Tests -- **dokumente**: 98 Tests +- **dokumente**: 116 Tests (98 in tests.py + 9 in test_json.py + 9 JSON-Tests in Haupt-tests.py) - **pages**: 4 Tests - **referenzen**: 18 Tests - **rollen**: 18 Tests diff --git a/Test suite.md b/Test suite.md index bd35611..f3f33ee 100644 --- a/Test suite.md +++ b/Test suite.md @@ -182,6 +182,21 @@ The dokumente app contains 98 tests, making it the most comprehensive test suite - **test_standard_history_view**: Tests standard detail view with historical check_date parameter - **test_standard_checkliste_view**: Tests checklist view functionality +### JSON Export Tests + +#### JSONExportManagementCommandTest +- **test_export_json_command_to_file**: Tests export_json command outputs JSON to specified file +- **test_export_json_command_stdout**: Tests export_json command outputs JSON to stdout when no file specified +- **test_export_json_command_inactive_documents**: Tests export_json command filters out inactive documents +- **test_export_json_command_empty_database**: Tests export_json command handles empty database gracefully + +#### StandardJSONViewTest +- **test_standard_json_view_success**: Tests standard_json view returns correct JSON for existing document +- **test_standard_json_view_not_found**: Tests standard_json view returns 404 for non-existent document +- **test_standard_json_view_json_formatting**: Tests standard_json view returns properly formatted JSON +- **test_standard_json_view_null_dates**: Tests standard_json view handles null date fields correctly +- **test_standard_json_view_empty_sections**: Tests standard_json view handles empty document sections + ### Incomplete Vorgaben Tests #### IncompleteVorgabenTest @@ -317,9 +332,9 @@ The stichworte app contains 18 tests covering keyword models and their ordering. ## Test Statistics -- **Total Tests**: 188 +- **Total Tests**: 206 - **abschnitte**: 32 tests -- **dokumente**: 98 tests +- **dokumente**: 116 tests (98 in tests.py + 9 in test_json.py + 9 JSON tests in main tests.py) - **pages**: 4 tests - **referenzen**: 18 tests - **rollen**: 18 tests diff --git a/dokumente/test_json.py b/dokumente/test_json.py new file mode 100644 index 0000000..d1654a9 --- /dev/null +++ b/dokumente/test_json.py @@ -0,0 +1,385 @@ +from django.test import TestCase, Client +from django.urls import reverse +from django.core.management import call_command +from datetime import date +from io import StringIO +import tempfile +import os +import json + +from dokumente.models import ( + Dokumententyp, Person, Thema, Dokument, Vorgabe, + VorgabeLangtext, VorgabeKurztext, Geltungsbereich, + Einleitung, Checklistenfrage, Changelog +) +from abschnitte.models import AbschnittTyp + + +class JSONExportManagementCommandTest(TestCase): + """Test cases for export_json management command""" + + def setUp(self): + """Set up test data for JSON export""" + # Create test data + self.dokumententyp = Dokumententyp.objects.create( + name="Standard IT-Sicherheit", + verantwortliche_ve="SR-SUR-SEC" + ) + + self.autor1 = Person.objects.create( + name="Max Mustermann", + funktion="Security Analyst" + ) + self.autor2 = Person.objects.create( + name="Erika Mustermann", + funktion="Security Manager" + ) + + self.thema = Thema.objects.create( + name="Access Control", + erklaerung="Zugangskontrolle" + ) + + self.dokument = Dokument.objects.create( + nummer="TEST-001", + dokumententyp=self.dokumententyp, + name="Test Standard", + gueltigkeit_von=date(2023, 1, 1), + gueltigkeit_bis=date(2025, 12, 31), + signatur_cso="CSO-123", + anhaenge="Anhang1.pdf, Anhang2.pdf", + aktiv=True + ) + self.dokument.autoren.add(self.autor1, self.autor2) + + self.vorgabe = Vorgabe.objects.create( + order=1, + nummer=1, + dokument=self.dokument, + thema=self.thema, + titel="Test Vorgabe", + gueltigkeit_von=date(2023, 1, 1), + gueltigkeit_bis=date(2025, 12, 31) + ) + + # Create text sections + self.abschnitttyp_text = AbschnittTyp.objects.create(abschnitttyp="text") + self.abschnitttyp_table = AbschnittTyp.objects.create(abschnitttyp="table") + + self.geltungsbereich = Geltungsbereich.objects.create( + geltungsbereich=self.dokument, + abschnitttyp=self.abschnitttyp_text, + inhalt="Dies ist der Geltungsbereich", + order=1 + ) + + self.einleitung = Einleitung.objects.create( + einleitung=self.dokument, + abschnitttyp=self.abschnitttyp_text, + inhalt="Dies ist die Einleitung", + order=1 + ) + + self.kurztext = VorgabeKurztext.objects.create( + abschnitt=self.vorgabe, + abschnitttyp=self.abschnitttyp_text, + inhalt="Dies ist der Kurztext", + order=1 + ) + + self.langtext = VorgabeLangtext.objects.create( + abschnitt=self.vorgabe, + abschnitttyp=self.abschnitttyp_table, + inhalt="Spalte1|Spalte2\nWert1|Wert2", + order=1 + ) + + self.checklistenfrage = Checklistenfrage.objects.create( + vorgabe=self.vorgabe, + frage="Ist die Zugriffskontrolle implementiert?" + ) + + self.changelog = Changelog.objects.create( + dokument=self.dokument, + datum=date(2023, 6, 1), + aenderung="Erste Version erstellt" + ) + self.changelog.autoren.add(self.autor1) + + def test_export_json_command_stdout(self): + """Test export_json command output to stdout""" + out = StringIO() + call_command('export_json', stdout=out) + + output = out.getvalue() + + # Check that output contains expected JSON structure + self.assertIn('"Typ": "Standard IT-Sicherheit"', output) + self.assertIn('"Nummer": "TEST-001"', output) + self.assertIn('"Name": "Test Standard"', output) + self.assertIn('"Max Mustermann"', output) + self.assertIn('"Erika Mustermann"', output) + self.assertIn('"Von": "2023-01-01"', output) + self.assertIn('"Bis": "2025-12-31"', output) + self.assertIn('"SignaturCSO": "CSO-123"', output) + self.assertIn('"Dies ist der Geltungsbereich"', output) + self.assertIn('"Dies ist die Einleitung"', output) + self.assertIn('"Dies ist der Kurztext"', output) + self.assertIn('"Ist die Zugriffskontrolle implementiert?"', output) + self.assertIn('"Erste Version erstellt"', output) + + def test_export_json_command_to_file(self): + """Test export_json command output to file""" + with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.json') as tmp_file: + tmp_filename = tmp_file.name + + try: + call_command('export_json', output=tmp_filename) + + # Read file content + with open(tmp_filename, 'r', encoding='utf-8') as f: + content = f.read() + + # Parse JSON to ensure it's valid + data = json.loads(content) + + # Verify structure + self.assertIsInstance(data, list) + self.assertEqual(len(data), 1) + + doc_data = data[0] + self.assertEqual(doc_data['Nummer'], 'TEST-001') + self.assertEqual(doc_data['Name'], 'Test Standard') + self.assertEqual(doc_data['Typ'], 'Standard IT-Sicherheit') + self.assertEqual(len(doc_data['Autoren']), 2) + self.assertIn('Max Mustermann', doc_data['Autoren']) + self.assertIn('Erika Mustermann', doc_data['Autoren']) + + finally: + # Clean up temporary file + if os.path.exists(tmp_filename): + os.unlink(tmp_filename) + + def test_export_json_command_empty_database(self): + """Test export_json command with no documents""" + # Delete all documents + Dokument.objects.all().delete() + + out = StringIO() + call_command('export_json', stdout=out) + + output = out.getvalue() + + # Should output empty array + self.assertEqual(output.strip(), '[]') + + def test_export_json_command_inactive_documents(self): + """Test export_json command filters inactive documents""" + # Create inactive document + inactive_doc = Dokument.objects.create( + nummer="INACTIVE-001", + dokumententyp=self.dokumententyp, + name="Inactive Document", + aktiv=False + ) + + out = StringIO() + call_command('export_json', stdout=out) + + output = out.getvalue() + + # Should not contain inactive document + self.assertNotIn('"INACTIVE-001"', output) + self.assertNotIn('"Inactive Document"', output) + + # Should still contain active document + self.assertIn('"TEST-001"', output) + self.assertIn('"Test Standard"', output) + + +class StandardJSONViewTest(TestCase): + """Test cases for standard_json view""" + + def setUp(self): + """Set up test data for JSON view""" + self.client = Client() + + # Create test data + self.dokumententyp = Dokumententyp.objects.create( + name="Standard IT-Sicherheit", + verantwortliche_ve="SR-SUR-SEC" + ) + + self.autor = Person.objects.create( + name="Test Autor", + funktion="Security Analyst" + ) + + self.pruefender = Person.objects.create( + name="Test Pruefender", + funktion="Security Manager" + ) + + self.thema = Thema.objects.create( + name="Access Control", + erklaerung="Zugangskontrolle" + ) + + self.dokument = Dokument.objects.create( + nummer="JSON-001", + dokumententyp=self.dokumententyp, + name="JSON Test Standard", + gueltigkeit_von=date(2023, 1, 1), + gueltigkeit_bis=date(2025, 12, 31), + signatur_cso="CSO-456", + anhaenge="test.pdf", + aktiv=True + ) + self.dokument.autoren.add(self.autor) + self.dokument.pruefende.add(self.pruefender) + + self.vorgabe = Vorgabe.objects.create( + order=1, + nummer=1, + dokument=self.dokument, + thema=self.thema, + titel="JSON Test Vorgabe", + gueltigkeit_von=date(2023, 1, 1), + gueltigkeit_bis=date(2025, 12, 31) + ) + + # Create text sections + self.abschnitttyp_text = AbschnittTyp.objects.create(abschnitttyp="text") + + self.geltungsbereich = Geltungsbereich.objects.create( + geltungsbereich=self.dokument, + abschnitttyp=self.abschnitttyp_text, + inhalt="Dies ist der Geltungsbereich", + order=1 + ) + + self.einleitung = Einleitung.objects.create( + einleitung=self.dokument, + abschnitttyp=self.abschnitttyp_text, + inhalt="Dies ist die Einleitung", + order=1 + ) + + self.kurztext = VorgabeKurztext.objects.create( + abschnitt=self.vorgabe, + abschnitttyp=self.abschnitttyp_text, + inhalt="JSON Kurztext", + order=1 + ) + + self.langtext = VorgabeLangtext.objects.create( + abschnitt=self.vorgabe, + abschnitttyp=self.abschnitttyp_text, + inhalt="JSON Langtext", + order=1 + ) + + self.checklistenfrage = Checklistenfrage.objects.create( + vorgabe=self.vorgabe, + frage="JSON Checklistenfrage?" + ) + + self.changelog = Changelog.objects.create( + dokument=self.dokument, + datum=date(2023, 6, 1), + aenderung="JSON Changelog Eintrag" + ) + self.changelog.autoren.add(self.autor) + + def test_standard_json_view_success(self): + """Test standard_json view returns correct JSON""" + url = reverse('standard_json', kwargs={'nummer': 'JSON-001'}) + response = self.client.get(url) + + self.assertEqual(response.status_code, 200) + self.assertEqual(response['Content-Type'], 'application/json') + + # Parse JSON response + data = json.loads(response.content) + + # Verify document structure + self.assertEqual(data['Nummer'], 'JSON-001') + self.assertEqual(data['Name'], 'JSON Test Standard') + self.assertEqual(data['Typ'], 'Standard IT-Sicherheit') + self.assertEqual(len(data['Autoren']), 1) + self.assertEqual(data['Autoren'][0], 'Test Autor') + self.assertEqual(len(data['Pruefende']), 1) + self.assertEqual(data['Pruefende'][0], 'Test Pruefender') + self.assertEqual(data['Gueltigkeit']['Von'], '2023-01-01') + self.assertEqual(data['Gueltigkeit']['Bis'], '2025-12-31') + self.assertEqual(data['SignaturCSO'], 'CSO-456') + self.assertEqual(data['Anhänge'], 'test.pdf') + self.assertEqual(data['Verantwortlich'], 'Information Security Management BIT') + self.assertIsNone(data['Klassifizierung']) + + def test_standard_json_view_not_found(self): + """Test standard_json view returns 404 for non-existent document""" + url = reverse('standard_json', kwargs={'nummer': 'NONEXISTENT'}) + response = self.client.get(url) + + self.assertEqual(response.status_code, 404) + + def test_standard_json_view_empty_sections(self): + """Test standard_json view handles empty sections correctly""" + # Create document without sections + empty_doc = Dokument.objects.create( + nummer="EMPTY-001", + dokumententyp=self.dokumententyp, + name="Empty Document", + aktiv=True + ) + + url = reverse('standard_json', kwargs={'nummer': 'EMPTY-001'}) + response = self.client.get(url) + + data = json.loads(response.content) + + # Verify empty sections are handled correctly + self.assertEqual(data['Geltungsbereich'], {}) + self.assertEqual(data['Einleitung'], {}) + self.assertEqual(data['Vorgaben'], []) + self.assertEqual(data['Changelog'], []) + + def test_standard_json_view_null_dates(self): + """Test standard_json view handles null dates correctly""" + # Create document with null dates + null_doc = Dokument.objects.create( + nummer="NULL-001", + dokumententyp=self.dokumententyp, + name="Null Dates Document", + gueltigkeit_von=None, + gueltigkeit_bis=None, + aktiv=True + ) + + url = reverse('standard_json', kwargs={'nummer': 'NULL-001'}) + response = self.client.get(url) + + data = json.loads(response.content) + + # Verify null dates are handled correctly + self.assertEqual(data['Gueltigkeit']['Von'], '') + self.assertIsNone(data['Gueltigkeit']['Bis']) + + def test_standard_json_view_json_formatting(self): + """Test standard_json view returns properly formatted JSON""" + url = reverse('standard_json', kwargs={'nummer': 'JSON-001'}) + response = self.client.get(url) + + # Check that response is valid JSON + try: + data = json.loads(response.content) + json_valid = True + except json.JSONDecodeError: + json_valid = False + + self.assertTrue(json_valid) + + # Check that JSON is properly indented (should be formatted) + self.assertIn('\n', response.content.decode()) + self.assertIn(' ', response.content.decode()) # Check for indentation \ No newline at end of file diff --git a/dokumente/tests.py b/dokumente/tests.py index 317df48..d988269 100644 --- a/dokumente/tests.py +++ b/dokumente/tests.py @@ -1135,3 +1135,374 @@ class IncompleteVorgabenTest(TestCase): self.client.login(username='teststaff', password='testpass123') response = self.client.get(reverse('incomplete_vorgaben')) self.assertEqual(response.status_code, 200) # Success + + +class JSONExportManagementCommandTest(TestCase): + """Test cases for export_json management command""" + + def setUp(self): + """Set up test data for JSON export""" + # Create test data + self.dokumententyp = Dokumententyp.objects.create( + name="Standard IT-Sicherheit", + verantwortliche_ve="SR-SUR-SEC" + ) + + self.autor1 = Person.objects.create( + name="Max Mustermann", + funktion="Security Analyst" + ) + self.autor2 = Person.objects.create( + name="Erika Mustermann", + funktion="Security Manager" + ) + + self.thema = Thema.objects.create( + name="Access Control", + erklaerung="Zugangskontrolle" + ) + + self.dokument = Dokument.objects.create( + nummer="TEST-001", + dokumententyp=self.dokumententyp, + name="Test Standard", + gueltigkeit_von=date(2023, 1, 1), + gueltigkeit_bis=date(2025, 12, 31), + signatur_cso="CSO-123", + anhaenge="Anhang1.pdf, Anhang2.pdf", + aktiv=True + ) + self.dokument.autoren.add(self.autor1, self.autor2) + + self.vorgabe = Vorgabe.objects.create( + order=1, + nummer=1, + dokument=self.dokument, + thema=self.thema, + titel="Test Vorgabe", + gueltigkeit_von=date(2023, 1, 1), + gueltigkeit_bis=date(2025, 12, 31) + ) + + # Create text sections + self.abschnitttyp_text = AbschnittTyp.objects.create(abschnitttyp="text") + self.abschnitttyp_table = AbschnittTyp.objects.create(abschnitttyp="table") + + self.geltungsbereich = Geltungsbereich.objects.create( + geltungsbereich=self.dokument, + abschnitttyp=self.abschnitttyp_text, + inhalt="Dies ist der Geltungsbereich", + order=1 + ) + + self.einleitung = Einleitung.objects.create( + einleitung=self.dokument, + abschnitttyp=self.abschnitttyp_text, + inhalt="Dies ist die Einleitung", + order=1 + ) + + self.kurztext = VorgabeKurztext.objects.create( + abschnitt=self.vorgabe, + abschnitttyp=self.abschnitttyp_text, + inhalt="Dies ist der Kurztext", + order=1 + ) + + self.langtext = VorgabeLangtext.objects.create( + abschnitt=self.vorgabe, + abschnitttyp=self.abschnitttyp_table, + inhalt="Spalte1|Spalte2\nWert1|Wert2", + order=1 + ) + + self.checklistenfrage = Checklistenfrage.objects.create( + vorgabe=self.vorgabe, + frage="Ist die Zugriffskontrolle implementiert?" + ) + + self.changelog = Changelog.objects.create( + dokument=self.dokument, + datum=date(2023, 6, 1), + aenderung="Erste Version erstellt" + ) + self.changelog.autoren.add(self.autor1) + + def test_export_json_command_stdout(self): + """Test export_json command output to stdout""" + out = StringIO() + call_command('export_json', stdout=out) + + output = out.getvalue() + + # Check that output contains expected JSON structure + self.assertIn('"Typ": "Standard IT-Sicherheit"', output) + self.assertIn('"Nummer": "TEST-001"', output) + self.assertIn('"Name": "Test Standard"', output) + self.assertIn('"Max Mustermann"', output) + self.assertIn('"Erika Mustermann"', output) + self.assertIn('"Von": "2023-01-01"', output) + self.assertIn('"Bis": "2025-12-31"', output) + self.assertIn('"SignaturCSO": "CSO-123"', output) + self.assertIn('"Dies ist der Geltungsbereich"', output) + self.assertIn('"Dies ist die Einleitung"', output) + self.assertIn('"Dies ist der Kurztext"', output) + self.assertIn('"Ist die Zugriffskontrolle implementiert?"', output) + self.assertIn('"Erste Version erstellt"', output) + + def test_export_json_command_to_file(self): + """Test export_json command output to file""" + import tempfile + import os + + with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.json') as tmp_file: + tmp_filename = tmp_file.name + + try: + call_command('export_json', output=tmp_filename) + + # Read file content + with open(tmp_filename, 'r', encoding='utf-8') as f: + content = f.read() + + # Parse JSON to ensure it's valid + import json + data = json.loads(content) + + # Verify structure + self.assertIsInstance(data, list) + self.assertEqual(len(data), 1) + + doc_data = data[0] + self.assertEqual(doc_data['Nummer'], 'TEST-001') + self.assertEqual(doc_data['Name'], 'Test Standard') + self.assertEqual(doc_data['Typ'], 'Standard IT-Sicherheit') + self.assertEqual(len(doc_data['Autoren']), 2) + self.assertIn('Max Mustermann', doc_data['Autoren']) + self.assertIn('Erika Mustermann', doc_data['Autoren']) + + finally: + # Clean up temporary file + if os.path.exists(tmp_filename): + os.unlink(tmp_filename) + + def test_export_json_command_empty_database(self): + """Test export_json command with no documents""" + # Delete all documents + Dokument.objects.all().delete() + + out = StringIO() + call_command('export_json', stdout=out) + + output = out.getvalue() + + # Should output empty array + self.assertEqual(output.strip(), '[]') + + def test_export_json_command_inactive_documents(self): + """Test export_json command filters inactive documents""" + # Create inactive document + inactive_doc = Dokument.objects.create( + nummer="INACTIVE-001", + dokumententyp=self.dokumententyp, + name="Inactive Document", + aktiv=False + ) + + out = StringIO() + call_command('export_json', stdout=out) + + output = out.getvalue() + + # Should not contain inactive document + self.assertNotIn('"INACTIVE-001"', output) + self.assertNotIn('"Inactive Document"', output) + + # Should still contain active document + self.assertIn('"TEST-001"', output) + self.assertIn('"Test Standard"', output) + + +class StandardJSONViewTest(TestCase): + """Test cases for standard_json view""" + + def setUp(self): + """Set up test data for JSON view""" + self.client = Client() + + # Create test data + self.dokumententyp = Dokumententyp.objects.create( + name="Standard IT-Sicherheit", + verantwortliche_ve="SR-SUR-SEC" + ) + + self.autor = Person.objects.create( + name="Test Autor", + funktion="Security Analyst" + ) + + self.pruefender = Person.objects.create( + name="Test Pruefender", + funktion="Security Manager" + ) + + self.thema = Thema.objects.create( + name="Access Control", + erklaerung="Zugangskontrolle" + ) + + self.dokument = Dokument.objects.create( + nummer="JSON-001", + dokumententyp=self.dokumententyp, + name="JSON Test Standard", + gueltigkeit_von=date(2023, 1, 1), + gueltigkeit_bis=date(2025, 12, 31), + signatur_cso="CSO-456", + anhaenge="test.pdf", + aktiv=True + ) + self.dokument.autoren.add(self.autor) + self.dokument.pruefende.add(self.pruefender) + + self.vorgabe = Vorgabe.objects.create( + order=1, + nummer=1, + dokument=self.dokument, + thema=self.thema, + titel="JSON Test Vorgabe", + gueltigkeit_von=date(2023, 1, 1), + gueltigkeit_bis=date(2025, 12, 31) + ) + + # Create text sections + self.abschnitttyp_text = AbschnittTyp.objects.create(abschnitttyp="text") + + self.geltungsbereich = Geltungsbereich.objects.create( + geltungsbereich=self.dokument, + abschnitttyp=self.abschnitttyp_text, + inhalt="JSON Geltungsbereich", + order=1 + ) + + self.kurztext = VorgabeKurztext.objects.create( + abschnitt=self.vorgabe, + abschnitttyp=self.abschnitttyp_text, + inhalt="JSON Kurztext", + order=1 + ) + + self.langtext = VorgabeLangtext.objects.create( + abschnitt=self.vorgabe, + abschnitttyp=self.abschnitttyp_text, + inhalt="JSON Langtext", + order=1 + ) + + self.checklistenfrage = Checklistenfrage.objects.create( + vorgabe=self.vorgabe, + frage="JSON Checklistenfrage?" + ) + + self.changelog = Changelog.objects.create( + dokument=self.dokument, + datum=date(2023, 6, 1), + aenderung="JSON Changelog Eintrag" + ) + self.changelog.autoren.add(self.autor) + + def test_standard_json_view_success(self): + """Test standard_json view returns correct JSON""" + url = reverse('standard_json', kwargs={'nummer': 'JSON-001'}) + response = self.client.get(url) + + self.assertEqual(response.status_code, 200) + self.assertEqual(response['Content-Type'], 'application/json') + + # Parse JSON response + import json + data = json.loads(response.content) + + # Verify document structure + self.assertEqual(data['Nummer'], 'JSON-001') + self.assertEqual(data['Name'], 'JSON Test Standard') + self.assertEqual(data['Typ'], 'Standard IT-Sicherheit') + self.assertEqual(len(data['Autoren']), 1) + self.assertEqual(data['Autoren'][0], 'Test Autor') + self.assertEqual(len(data['Pruefende']), 1) + self.assertEqual(data['Pruefende'][0], 'Test Pruefender') + self.assertEqual(data['Gueltigkeit']['Von'], '2023-01-01') + self.assertEqual(data['Gueltigkeit']['Bis'], '2025-12-31') + self.assertEqual(data['SignaturCSO'], 'CSO-456') + self.assertEqual(data['Anhänge'], 'test.pdf') + self.assertEqual(data['Verantwortlich'], 'Information Security Management BIT') + self.assertIsNone(data['Klassifizierung']) + + def test_standard_json_view_not_found(self): + """Test standard_json view returns 404 for non-existent document""" + url = reverse('standard_json', kwargs={'nummer': 'NONEXISTENT'}) + response = self.client.get(url) + + self.assertEqual(response.status_code, 404) + + def test_standard_json_view_empty_sections(self): + """Test standard_json view handles empty sections correctly""" + # Create document without sections + empty_doc = Dokument.objects.create( + nummer="EMPTY-001", + dokumententyp=self.dokumententyp, + name="Empty Document", + aktiv=True + ) + + url = reverse('standard_json', kwargs={'nummer': 'EMPTY-001'}) + response = self.client.get(url) + + import json + data = json.loads(response.content) + + # Verify empty sections are handled correctly + self.assertEqual(data['Geltungsbereich'], {}) + self.assertEqual(data['Einleitung'], {}) + self.assertEqual(data['Vorgaben'], []) + self.assertEqual(data['Changelog'], []) + + def test_standard_json_view_null_dates(self): + """Test standard_json view handles null dates correctly""" + # Create document with null dates + null_doc = Dokument.objects.create( + nummer="NULL-001", + dokumententyp=self.dokumententyp, + name="Null Dates Document", + gueltigkeit_von=None, + gueltigkeit_bis=None, + aktiv=True + ) + + url = reverse('standard_json', kwargs={'nummer': 'NULL-001'}) + response = self.client.get(url) + + import json + data = json.loads(response.content) + + # Verify null dates are handled correctly + self.assertEqual(data['Gueltigkeit']['Von'], '') + self.assertIsNone(data['Gueltigkeit']['Bis']) + + def test_standard_json_view_json_formatting(self): + """Test standard_json view returns properly formatted JSON""" + url = reverse('standard_json', kwargs={'nummer': 'JSON-001'}) + response = self.client.get(url) + + # Check that response is valid JSON + import json + try: + data = json.loads(response.content) + json_valid = True + except json.JSONDecodeError: + json_valid = False + + self.assertTrue(json_valid) + + # Check that JSON is properly indented (should be formatted) + self.assertIn('\n', response.content.decode()) + self.assertIn(' ', response.content.decode()) # Check for indentation