test+docs(iace): add handler tests, error-handling tests, JSON export tests, TipTap docs
All checks were successful
CI/CD / go-lint (push) Has been skipped
CI/CD / python-lint (push) Has been skipped
CI/CD / nodejs-lint (push) Has been skipped
CI/CD / test-go-ai-compliance (push) Successful in 38s
CI/CD / test-python-backend-compliance (push) Successful in 34s
CI/CD / test-python-document-crawler (push) Successful in 29s
CI/CD / test-python-dsms-gateway (push) Successful in 20s
CI/CD / validate-canonical-controls (push) Successful in 12s
CI/CD / Deploy (push) Successful in 2s
All checks were successful
CI/CD / go-lint (push) Has been skipped
CI/CD / python-lint (push) Has been skipped
CI/CD / nodejs-lint (push) Has been skipped
CI/CD / test-go-ai-compliance (push) Successful in 38s
CI/CD / test-python-backend-compliance (push) Successful in 34s
CI/CD / test-python-document-crawler (push) Successful in 29s
CI/CD / test-python-dsms-gateway (push) Successful in 20s
CI/CD / validate-canonical-controls (push) Successful in 12s
CI/CD / Deploy (push) Successful in 2s
- Create iace_handler_test.go (22 tests): input validation for InitFromProfile, GenerateSingleSection, ExportTechFile, CheckCompleteness, getTenantID, CreateProject, ListProjects, Component CRUD handlers - Add error-handling tests to tech_file_generator_test.go: nil context, nil project, empty components/hazards/classifications/evidence, unknown section type, all 19 getSystemPrompt types, AI-specific section prompts - Add JSON export tests to document_export_test.go: valid output, empty project, nil project error, special character handling (German text, XML escapes) - Add iace-hazard-library.md to mkdocs.yml navigation - Add TipTap Rich-Text-Editor section to iace.md documentation Total: 181 tests passing (was 165), 0 failures Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -484,6 +484,133 @@ func TestBuildUserPrompt_DeclarationOfConformity(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Tests: Error handling & edge cases
|
||||
// ============================================================================
|
||||
|
||||
func TestBuildUserPrompt_NilContext(t *testing.T) {
|
||||
// Should not panic on completely nil context
|
||||
prompt := buildUserPrompt(nil, "risk_assessment_report")
|
||||
if prompt == "" {
|
||||
t.Error("buildUserPrompt should return non-empty string for nil context")
|
||||
}
|
||||
if !strings.Contains(prompt, "Keine Projektdaten") {
|
||||
t.Error("nil context prompt should contain fallback text 'Keine Projektdaten'")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildUserPrompt_NilProject(t *testing.T) {
|
||||
sctx := &SectionGenerationContext{
|
||||
Project: nil,
|
||||
}
|
||||
prompt := buildUserPrompt(sctx, "general_description")
|
||||
if prompt == "" {
|
||||
t.Error("buildUserPrompt should return non-empty string for nil project")
|
||||
}
|
||||
if !strings.Contains(prompt, "Keine Projektdaten") {
|
||||
t.Error("nil project prompt should contain fallback text 'Keine Projektdaten'")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildUserPrompt_EmptyComponents(t *testing.T) {
|
||||
sctx := &SectionGenerationContext{
|
||||
Project: &Project{MachineName: "Test", Manufacturer: "Corp"},
|
||||
Components: []Component{},
|
||||
Hazards: nil,
|
||||
}
|
||||
prompt := buildUserPrompt(sctx, "component_list")
|
||||
if !strings.Contains(prompt, "Test") {
|
||||
t.Error("prompt should contain machine name even with empty components")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildUserPrompt_EmptyHazards(t *testing.T) {
|
||||
sctx := &SectionGenerationContext{
|
||||
Project: &Project{MachineName: "Test", Manufacturer: "Corp"},
|
||||
Hazards: []Hazard{},
|
||||
}
|
||||
prompt := buildUserPrompt(sctx, "hazard_log_combined")
|
||||
if prompt == "" {
|
||||
t.Error("prompt should be non-empty even with no hazards")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildUserPrompt_EmptyClassifications(t *testing.T) {
|
||||
sctx := &SectionGenerationContext{
|
||||
Project: &Project{MachineName: "Test", Manufacturer: "Corp"},
|
||||
Classifications: []RegulatoryClassification{},
|
||||
}
|
||||
prompt := buildUserPrompt(sctx, "classification_report")
|
||||
if prompt == "" {
|
||||
t.Error("prompt should be non-empty even with no classifications")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildUserPrompt_EmptyEvidence(t *testing.T) {
|
||||
sctx := &SectionGenerationContext{
|
||||
Project: &Project{MachineName: "Test", Manufacturer: "Corp"},
|
||||
Evidence: []Evidence{},
|
||||
}
|
||||
prompt := buildUserPrompt(sctx, "evidence_index")
|
||||
if prompt == "" {
|
||||
t.Error("prompt should be non-empty even with no evidence")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetSystemPrompt_UnknownType(t *testing.T) {
|
||||
prompt := getSystemPrompt("totally_unknown_section")
|
||||
if prompt == "" {
|
||||
t.Error("getSystemPrompt should return a fallback for unknown types")
|
||||
}
|
||||
// Fallback should still be a useful CE expert prompt
|
||||
lower := strings.ToLower(prompt)
|
||||
if !strings.Contains(lower, "ce") && !strings.Contains(lower, "experte") && !strings.Contains(lower, "dokumentation") {
|
||||
t.Error("fallback system prompt should reference CE or documentation expertise")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetSystemPrompt_AllKnownTypes(t *testing.T) {
|
||||
knownTypes := []string{
|
||||
"risk_assessment_report", "hazard_log_combined", "general_description",
|
||||
"essential_requirements", "design_specifications", "test_reports",
|
||||
"standards_applied", "declaration_of_conformity", "component_list",
|
||||
"classification_report", "mitigation_report", "verification_report",
|
||||
"evidence_index", "instructions_for_use", "monitoring_plan",
|
||||
"ai_intended_purpose", "ai_model_description", "ai_risk_management",
|
||||
"ai_human_oversight",
|
||||
}
|
||||
for _, st := range knownTypes {
|
||||
t.Run(st, func(t *testing.T) {
|
||||
prompt := getSystemPrompt(st)
|
||||
if prompt == "" {
|
||||
t.Errorf("getSystemPrompt(%q) returned empty string", st)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildUserPrompt_AIIntendedPurpose(t *testing.T) {
|
||||
sctx := newTestSectionContext()
|
||||
prompt := buildUserPrompt(sctx, "ai_intended_purpose")
|
||||
if prompt == "" {
|
||||
t.Error("prompt should be non-empty for ai_intended_purpose")
|
||||
}
|
||||
if !strings.Contains(prompt, "Robot Arm XY-200") {
|
||||
t.Error("AI intended purpose prompt should contain machine name")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildUserPrompt_AIHumanOversight(t *testing.T) {
|
||||
sctx := newTestSectionContext()
|
||||
prompt := buildUserPrompt(sctx, "ai_human_oversight")
|
||||
if prompt == "" {
|
||||
t.Error("prompt should be non-empty for ai_human_oversight")
|
||||
}
|
||||
if !strings.Contains(prompt, "Robot Arm XY-200") {
|
||||
t.Error("AI human oversight prompt should contain machine name")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildUserPrompt_MultipleHazardAssessments(t *testing.T) {
|
||||
sctx := newTestSectionContext()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user