33using Ellabit . Challenges ;
44using Ellabit . DynamicCode ;
55using Ellabit . Monaco ;
6+ using Ellabit . Pages . Models ;
67using IronBlock . Blocks ;
78using Microsoft . AspNetCore . Components ;
89using Microsoft . CodeAnalysis ;
@@ -43,7 +44,7 @@ public partial class Challenge : ComponentBase, IDisposable
4344 bool _isDarkMode = false ;
4445 int prevTabIndex = - 1 ;
4546 string ? code = string . Empty ;
46- string testResults = "" ;
47+ List < TestDisplayResult > resultList = new ( ) ;
4748 bool fail = true ;
4849 bool runningTests = false ;
4950 protected override void OnInitialized ( )
@@ -122,13 +123,13 @@ public async void OnBlocklyToCSharp()
122123 SyntaxNode syntax = CSharpSyntaxTree . ParseText ( _unloadable . Context . Challenge . Code ?? "" ) . GetRoot ( ) ;
123124 MethodDeclarationSyntax method = ( from node in syntax . DescendantNodes ( )
124125 . OfType < MethodDeclarationSyntax > ( )
125- select node ) . First ( ) ;
126+ select node ) . First ( ) ;
126127 if ( method . Body != null )
127128 {
128129 var methodBody = ( SyntaxNode ) method . Body ;
129130 //Replace
130131 var output = syntax . ReplaceNode ( methodBody , blockMethodBlock ) ;
131-
132+
132133 output = output . SyntaxTree . GetRoot ( ) . NormalizeWhitespace ( ) ;
133134 code = output . ToFullString ( ) ;
134135 }
@@ -146,7 +147,7 @@ public static string Evaluate(string xml)
146147
147148 var blockMethodBody = ( from method in blockSyntax . DescendantNodes ( )
148149 . OfType < LocalFunctionStatementSyntax > ( )
149- select method . Body ) . FirstOrDefault ( ) ;
150+ select method . Body ) . FirstOrDefault ( ) ;
150151
151152 return blockMethodBody ? . ToFullString ( ) ?? "" ;
152153
@@ -159,7 +160,7 @@ public void SetChallenge()
159160 {
160161 ChallengeId = 0 ;
161162 }
162- if ( Challenges . Count < ( ChallengeId ?? 0 ) )
163+ if ( Challenges . Count < ( ChallengeId ?? 0 ) )
163164 {
164165 if ( NavMan == null )
165166 {
@@ -207,7 +208,7 @@ public async Task TabChanged_ClearEditor()
207208 }
208209 if ( _editor != null && _unloadable ? . Context ? . Challenge != null && prevTabIndex == TabIDCode ( ) )
209210 {
210- code = await _editor . GetValue ( ) ;
211+ code = await _editor . GetValue ( ) ;
211212 }
212213 }
213214 public int TabIDBlockly ( )
@@ -242,28 +243,42 @@ public async Task TabChanged_LoadEditor()
242243 public async void OnExecuteTests ( )
243244 {
244245 ClearChallengeCache ( ) ;
245- testResults = "" ;
246246 StateHasChanged ( ) ;
247247 await ExecuteTests ( ) ;
248248 }
249249 private async Task ExecuteTests ( )
250250 {
251- testResults = "" ;
251+ resultList . Clear ( ) ;
252252 if ( ! ( _unloadable ? . Context ? . Challenge is IChallenge ) )
253253 {
254- testResults += "\n Challenge, missing IChallenge" ;
254+ resultList . Add ( new TestDisplayResult
255+ {
256+ Number = 0 ,
257+ Passed = false ,
258+ Message = "Challenge missing IChallenge interface"
259+ } ) ;
255260 return ;
256261 }
257262 if ( ! ( _unloadable ? . Context ? . Challenge is IChallengeTestCode ) )
258263 {
259- testResults += "\n Invalid Challenge, missing IChallengeTestCode" ;
264+ resultList . Add ( new TestDisplayResult
265+ {
266+ Number = 0 ,
267+ Passed = false ,
268+ Message = "Invalid Challenge, missing IChallengeTestCode"
269+ } ) ;
260270 return ;
261271 }
262272 var testCode = _unloadable ? . Context ? . Challenge as IChallengeTestCode ;
263273
264274 if ( testCode . Tests == null )
265275 {
266- testResults += "\n Code didn't compile" ;
276+ resultList . Add ( new TestDisplayResult
277+ {
278+ Number = 0 ,
279+ Passed = false ,
280+ Message = "Code did not compile"
281+ } ) ;
267282 return ;
268283 }
269284 var origCode = _unloadable ? . Context ? . Challenge ? . Code ;
@@ -278,44 +293,35 @@ private async Task ExecuteTests()
278293 {
279294 try
280295 {
281- var testResult = await _unloadable . Context . RunTest ( test ) ;
282- if ( testResult . pass )
283- {
284- testResults += $ "<br/>Test { testNum } <h6 style='color: green'>Pass</h6>";
285- }
286- else
296+ var result = await _unloadable . Context . RunTest ( test ) ;
297+ var ( actual , expected ) = ExtractValues ( result . message ?? "" ) ;
298+
299+ resultList . Add ( new TestDisplayResult
287300 {
288- testResults += $ "<br/>Test { testNum } <h6 style='color: red'>FAILED</h6> " + testResult . message ;
289- fail = true ;
290- }
301+ Number = testNum ,
302+ Passed = result . pass ,
303+ ExpectedValue = expected ,
304+ ActualValue = actual ,
305+ } ) ;
306+
307+ if ( ! result . pass ) fail = true ;
291308 }
292309 catch ( Exception ex )
293310 {
294311 fail = true ;
295- if ( ex is IOException )
312+
313+ resultList . Add ( new TestDisplayResult
296314 {
297- testResults += $ "<br/><h6 style='color: red'>FAILED</h6> " + ex . Message ;
298- return ;
299- }
300- testResults += $ "<br/>Test { testNum } " + "\n <h6 style='color: red'>FAILED</h6> " + ex . Message ;
315+ Number = testNum ,
316+ Passed = false ,
317+ Message = ex . Message
318+ } ) ;
319+
320+ if ( ex is IOException ) return ;
301321 }
302- testNum ++ ;
303- }
304322
305- }
306- catch ( Exception ex )
307- {
308- if ( DialogService != null )
309- {
310- await DialogService . ShowMessageBox (
311- "Error" ,
312- ex . Message ,
313- yesText : "OK" ) ;
314- StateHasChanged ( ) ;
323+ testNum ++ ;
315324 }
316-
317- testResults += "\n Unexpected Error " + ex . Message ;
318- return ;
319325 }
320326 finally
321327 {
@@ -339,7 +345,7 @@ public void OnNextChallenge()
339345 {
340346 NavMan . NavigateTo ( $ "/Ellabit/{ ChallengeId } ") ;
341347 } else
342- {
348+ {
343349 NavMan . NavigateTo ( $ "/{ ChallengeId } ") ;
344350 }
345351 }
@@ -375,5 +381,23 @@ public void Dispose()
375381 {
376382 _objRef ? . Dispose ( ) ;
377383 }
384+ private ( string actual , string expected ) ExtractValues ( string message )
385+ {
386+ if ( string . IsNullOrWhiteSpace ( message ) )
387+ return ( "" , "" ) ;
388+
389+ var actualMatch = System . Text . RegularExpressions . Regex . Match (
390+ message , @"returned:\s*([^ ]+)" ,
391+ System . Text . RegularExpressions . RegexOptions . IgnoreCase ) ;
392+
393+ var expectedMatch = System . Text . RegularExpressions . Regex . Match (
394+ message , @"expected:\s*([^ ]+)" ,
395+ System . Text . RegularExpressions . RegexOptions . IgnoreCase ) ;
396+
397+ var actual = actualMatch . Success ? actualMatch . Groups [ 1 ] . Value : "" ;
398+ var expected = expectedMatch . Success ? expectedMatch . Groups [ 1 ] . Value : "" ;
399+
400+ return ( actual , expected ) ;
401+ }
378402 }
379403}
0 commit comments