@@ -50,13 +50,177 @@ func TestNew_ValidConfig(t *testing.T) {
5050 assert .Contains (t , err .Error (), "results directory is required" )
5151}
5252
53- func TestEmbeddedPromptTemplate (t * testing.T ) {
54- // Verify the embedded prompt template loads correctly
55- data , err := krknaiTemplatesFS .ReadFile ("prompts/krknai.yaml" )
53+ func TestPromptTemplatesAvailable (t * testing.T ) {
54+ store := newTestPromptStore (t )
55+
56+ tmpl , err := store .GetTemplate ("krknai" )
57+ require .NoError (t , err )
58+ assert .Contains (t , tmpl .SystemPrompt , "chaos engineering" )
59+ assert .Contains (t , tmpl .UserPrompt , "Summary" )
60+
61+ assert .Contains (t , tmpl .SystemPrompt , "markdown" )
62+ assert .Contains (t , tmpl .SystemPrompt , "genetic algorithm" )
63+ }
64+
65+ func TestRenderKrknAIPrompt (t * testing.T ) {
66+ store := newTestPromptStore (t )
67+
68+ variables := map [string ]any {
69+ "ClusterInfo" : & analysisengine.ClusterInfo {
70+ ID : "abc-123" ,
71+ Name : "test-rosa-cluster" ,
72+ Version : "4.17.3" ,
73+ Type : "rosa-hcp" ,
74+ Provider : "aws" ,
75+ Region : "us-east-1" ,
76+ Hypershift : true ,
77+ },
78+ "Summary" : map [string ]any {
79+ "TotalScenarioCount" : 30 ,
80+ "SuccessfulScenarioCount" : 27 ,
81+ "FailedScenarioCount" : 3 ,
82+ "Generations" : 3 ,
83+ "MaxFitnessScore" : 8.75 ,
84+ "AvgFitnessScore" : 4.32 ,
85+ "ScenarioTypes" : []string {"node-cpu-hog" , "node-memory-hog" , "pod-scenarios" },
86+ },
87+ "TopScenarios" : []map [string ]any {
88+ {
89+ "Scenario" : "node-cpu-hog" ,
90+ "GenerationID" : 2 ,
91+ "ScenarioID" : 15 ,
92+ "FitnessScore" : 8.75 ,
93+ "HealthCheckResponseTimeScore" : 6.50 ,
94+ "HealthCheckFailureScore" : 2.25 ,
95+ "KrknFailureScore" : 0.0 ,
96+ "Parameters" : "node_selector: node-role.kubernetes.io/worker" ,
97+ },
98+ },
99+ "FailedScenarios" : []map [string ]any {
100+ {
101+ "Scenario" : "dns-outage" ,
102+ "GenerationID" : 1 ,
103+ "ScenarioID" : 7 ,
104+ "KrknFailureScore" : - 1.0 ,
105+ "Parameters" : "namespace: openshift-dns" ,
106+ },
107+ },
108+ "HealthCheckReport" : []map [string ]any {
109+ {
110+ "ScenarioID" : 15 ,
111+ "ComponentName" : "console" ,
112+ "MinResponseTime" : 12.5 ,
113+ "MaxResponseTime" : 850.3 ,
114+ "AverageResponseTime" : 245.7 ,
115+ "SuccessCount" : 48 ,
116+ "FailureCount" : 2 ,
117+ },
118+ },
119+ "LogArtifacts" : []map [string ]any {
120+ {"Source" : "/results/reports/all.csv" , "LineCount" : 31 },
121+ {"Source" : "/results/krkn-ai.yaml" , "LineCount" : 85 },
122+ },
123+ "ConfigSummary" : "generations: 3\n population_size: 10\n " ,
124+ }
125+
126+ userPrompt , config , err := store .RenderPrompt ("krknai" , variables )
127+ require .NoError (t , err )
128+ require .NotNil (t , config )
129+
130+ assert .Contains (t , userPrompt , "id=abc-123" )
131+ assert .Contains (t , userPrompt , "name=test-rosa-cluster" )
132+ assert .Contains (t , userPrompt , "version=4.17.3" )
133+ assert .Contains (t , userPrompt , "type=rosa-hcp" )
134+ assert .Contains (t , userPrompt , "hypershift=true" )
135+
136+ assert .Contains (t , userPrompt , "30 scenarios" )
137+ assert .Contains (t , userPrompt , "27 ok" )
138+ assert .Contains (t , userPrompt , "3 failed" )
139+ assert .Contains (t , userPrompt , "max=8.75" )
140+ assert .Contains (t , userPrompt , "fitness=8.75" )
141+ assert .Contains (t , userPrompt , "node_selector: node-role.kubernetes.io/worker" )
142+ assert .Contains (t , userPrompt , "dns-outage" )
143+ assert .Contains (t , userPrompt , "console" )
144+ assert .Contains (t , userPrompt , "avg=245.70ms" )
145+ assert .Contains (t , userPrompt , "/results/reports/all.csv (31L)" )
146+ assert .Contains (t , userPrompt , "generations: 3" )
147+
148+ assert .NotNil (t , config .SystemInstruction )
149+ assert .Contains (t , * config .SystemInstruction , "chaos engineering analyst" )
150+ assert .Contains (t , * config .SystemInstruction , "genetic algorithm" )
151+ }
152+
153+ func TestRun_MarkdownReportFormat (t * testing.T ) {
154+ tempDir := t .TempDir ()
155+ reportsDir := filepath .Join (tempDir , "reports" )
156+ require .NoError (t , os .MkdirAll (reportsDir , 0o755 ))
157+
158+ createTestResultFiles (t , tempDir , reportsDir )
159+
160+ ctx := context .Background ()
161+ agg := krknAggregator .NewKrknAIAggregator (ctx )
162+ promptStore := newTestPromptStore (t )
163+
164+ mockClient := & mockLLMClient {
165+ response : & llm.AnalysisResult {
166+ Content : "# Krkn-AI Chaos Test Report\n \n ## Executive Summary\n Cluster shows moderate resilience." ,
167+ },
168+ }
169+
170+ engine := & Engine {
171+ config : & Config {
172+ BaseConfig : analysisengine.BaseConfig {ArtifactsDir : tempDir , APIKey : "fake-key" },
173+ ReportFormat : "markdown" ,
174+ },
175+ aggregator : agg ,
176+ promptStore : promptStore ,
177+ llmClient : mockClient ,
178+ reporterRegistry : newTestReporterRegistry (),
179+ }
180+
181+ result , err := engine .Run (ctx )
56182 require .NoError (t , err )
57- assert .Contains (t , string (data ), "system_prompt" )
58- assert .Contains (t , string (data ), "user_prompt" )
59- assert .Contains (t , string (data ), "chaos engineering" )
183+ require .NotNil (t , result )
184+ assert .Contains (t , result .Content , "Chaos Test Report" )
185+ }
186+
187+ func TestRun_HTMLReportFormat (t * testing.T ) {
188+ tempDir := t .TempDir ()
189+ reportsDir := filepath .Join (tempDir , "reports" )
190+ require .NoError (t , os .MkdirAll (reportsDir , 0o755 ))
191+
192+ createTestResultFiles (t , tempDir , reportsDir )
193+
194+ ctx := context .Background ()
195+ agg := krknAggregator .NewKrknAIAggregator (ctx )
196+ promptStore := newTestPromptStore (t )
197+
198+ mockClient := & mockLLMClient {
199+ response : & llm.AnalysisResult {
200+ Content : "# Krkn-AI Chaos Test Report\n \n ## Executive Summary\n Cluster shows **moderate** resilience.\n \n | Metric | Value |\n |--------|-------|\n | Total | 5 |\n " ,
201+ },
202+ }
203+
204+ engine := & Engine {
205+ config : & Config {
206+ BaseConfig : analysisengine.BaseConfig {ArtifactsDir : tempDir , APIKey : "fake-key" },
207+ ReportFormat : "html" ,
208+ },
209+ aggregator : agg ,
210+ promptStore : promptStore ,
211+ llmClient : mockClient ,
212+ reporterRegistry : newTestReporterRegistry (),
213+ }
214+
215+ result , err := engine .Run (ctx )
216+ require .NoError (t , err )
217+ require .NotNil (t , result )
218+
219+ assert .Contains (t , result .Content , "<!DOCTYPE html>" )
220+ assert .Contains (t , result .Content , "<h1" )
221+ assert .Contains (t , result .Content , "<table>" )
222+ assert .Contains (t , result .Content , "<strong>moderate</strong>" )
223+ assert .NotContains (t , result .Content , "## Executive Summary" )
60224}
61225
62226func TestWriteSummary (t * testing.T ) {
@@ -96,7 +260,7 @@ func TestWriteSummary(t *testing.T) {
96260 },
97261 }
98262
99- err := engine .writeSummary (result , data )
263+ err := engine .writeSummary (result , data , nil )
100264 require .NoError (t , err )
101265
102266 // Verify summary file exists
@@ -224,13 +388,16 @@ func TestRun_MissingResults(t *testing.T) {
224388 assert .Contains (t , err .Error (), "failed to collect krkn-ai results" )
225389}
226390
227- // newTestPromptStore creates a prompt store using the embedded krkn-ai templates.
391+ // newTestPromptStore creates a prompt store using the central prompt templates.
228392func newTestPromptStore (t * testing.T ) * prompts.PromptStore {
229393 t .Helper ()
230- templatesFS , err := fs . Sub ( krknaiTemplatesFS , " prompts" )
394+ store , err := prompts . NewPromptStore ( prompts . DefaultTemplates () )
231395 require .NoError (t , err )
232- store , err := prompts .NewPromptStore (templatesFS )
396+
397+ localFS , err := fs .Sub (krknPrompts , "prompts" )
233398 require .NoError (t , err )
399+ require .NoError (t , store .RegisterTemplates (localFS ))
400+
234401 return store
235402}
236403
0 commit comments