@@ -1347,5 +1347,170 @@ public void CreateResult_WithExitCode106_SerializesToValidJson()
13471347 }
13481348
13491349 #endregion
1350+
1351+ #region ParseBuildOutput Tests
1352+
1353+ [ Fact ]
1354+ public void ParseBuildOutput_WithCompilerError_ReturnsFailureWithDiagnostic ( )
1355+ {
1356+ // Arrange - simulate what DotNetCommandExecutor.ExecuteCommandAsync returns for a failed build
1357+ var rawOutput = """
1358+ Command: dotnet build "MyProject.csproj"
1359+ Build FAILED.
1360+
1361+ Build FAILED.
1362+
1363+ Error(s)
1364+ Program.cs(9,51): error CS0246: The type or namespace name 'IRenderable' could not be found (are you missing a using directive or an assembly reference?) [MyProject.csproj]
1365+ 0 Warning(s)
1366+ 1 Error(s)
1367+
1368+ Exit Code: 1
1369+ """ ;
1370+
1371+ // Act
1372+ var result = ErrorResultFactory . ParseBuildOutput ( rawOutput , project : "MyProject.csproj" , configuration : "Debug" ) ;
1373+
1374+ // Assert
1375+ Assert . False ( result . Success ) ;
1376+ Assert . Equal ( "MyProject.csproj" , result . Project ) ;
1377+ Assert . Equal ( "Debug" , result . Configuration ) ;
1378+ Assert . Equal ( 1 , result . ErrorCount ) ;
1379+ Assert . Equal ( 0 , result . WarningCount ) ;
1380+ Assert . Contains ( "FAILED" , result . Summary , StringComparison . OrdinalIgnoreCase ) ;
1381+
1382+ Assert . NotNull ( result . Errors ) ;
1383+ var diag = Assert . Single ( result . Errors ) ;
1384+ Assert . Equal ( "CS0246" , diag . Code ) ;
1385+ Assert . Contains ( "IRenderable" , diag . Message ) ;
1386+ Assert . Equal ( "error" , diag . Severity ) ;
1387+ Assert . Equal ( 9 , diag . Line ) ;
1388+ Assert . Equal ( 51 , diag . Column ) ;
1389+ Assert . False ( string . IsNullOrWhiteSpace ( diag . File ) ) ;
1390+ Assert . Contains ( "Program.cs" , diag . File ) ;
1391+
1392+ Assert . Null ( result . Warnings ) ;
1393+ }
1394+
1395+ [ Fact ]
1396+ public void ParseBuildOutput_WithWarning_ReturnsSuccessWithWarningDiagnostic ( )
1397+ {
1398+ // Arrange
1399+ var rawOutput = """
1400+ Command: dotnet build "MyProject.csproj"
1401+ Program.cs(3,1): warning CS0219: The variable 'x' is assigned but its value is never used [MyProject.csproj]
1402+ Build succeeded.
1403+ 1 Warning(s)
1404+ 0 Error(s)
1405+
1406+ Exit Code: 0
1407+ """ ;
1408+
1409+ // Act
1410+ var result = ErrorResultFactory . ParseBuildOutput ( rawOutput , project : "MyProject.csproj" ) ;
1411+
1412+ // Assert
1413+ Assert . True ( result . Success ) ;
1414+ Assert . Equal ( 0 , result . ErrorCount ) ;
1415+ Assert . Equal ( 1 , result . WarningCount ) ;
1416+ Assert . Contains ( "succeeded" , result . Summary , StringComparison . OrdinalIgnoreCase ) ;
1417+
1418+ Assert . Null ( result . Errors ) ;
1419+ Assert . NotNull ( result . Warnings ) ;
1420+ var diag = Assert . Single ( result . Warnings ) ;
1421+ Assert . Equal ( "CS0219" , diag . Code ) ;
1422+ Assert . Equal ( "warning" , diag . Severity ) ;
1423+ Assert . Equal ( 3 , diag . Line ) ;
1424+ Assert . Equal ( 1 , diag . Column ) ;
1425+ }
1426+
1427+ [ Fact ]
1428+ public void ParseBuildOutput_WithSuccessNoWarnings_ReturnsCleanSuccess ( )
1429+ {
1430+ // Arrange
1431+ var rawOutput = """
1432+ Command: dotnet build "MyProject.csproj"
1433+ Build succeeded.
1434+ 0 Warning(s)
1435+ 0 Error(s)
1436+
1437+ Exit Code: 0
1438+ """ ;
1439+
1440+ // Act
1441+ var result = ErrorResultFactory . ParseBuildOutput ( rawOutput , project : "MyProject.csproj" ) ;
1442+
1443+ // Assert
1444+ Assert . True ( result . Success ) ;
1445+ Assert . Equal ( 0 , result . ErrorCount ) ;
1446+ Assert . Equal ( 0 , result . WarningCount ) ;
1447+ Assert . Equal ( "Build succeeded" , result . Summary ) ;
1448+ Assert . Null ( result . Errors ) ;
1449+ Assert . Null ( result . Warnings ) ;
1450+ }
1451+
1452+ [ Fact ]
1453+ public void ParseBuildOutput_WithNullInput_ReturnsSafeSuccess ( )
1454+ {
1455+ var result = ErrorResultFactory . ParseBuildOutput ( null ! ) ;
1456+ Assert . True ( result . Success ) ;
1457+ }
1458+
1459+ [ Fact ]
1460+ public void ParseBuildOutput_WithEmptyInput_ReturnsSafeSuccess ( )
1461+ {
1462+ var result = ErrorResultFactory . ParseBuildOutput ( string . Empty ) ;
1463+ Assert . True ( result . Success ) ;
1464+ }
1465+
1466+ [ Fact ]
1467+ public void ParseBuildOutput_WithAbsoluteProjectPath_SanitizesToFilename ( )
1468+ {
1469+ // Absolute project paths should be reduced to just the filename to avoid leaking machine paths.
1470+ // Path.GetFullPath ensures this is a rooted/absolute path on any platform.
1471+ var absolutePath = Path . GetFullPath ( Path . Join ( "my-project" , "MyApp.csproj" ) ) ;
1472+ var rawOutput = "Command: dotnet build\n Build succeeded.\n 0 Warning(s)\n 0 Error(s)\n Exit Code: 0" ;
1473+
1474+ var result = ErrorResultFactory . ParseBuildOutput ( rawOutput , project : absolutePath ) ;
1475+
1476+ Assert . True ( result . Success ) ;
1477+ Assert . Equal ( "MyApp.csproj" , result . Project ) ;
1478+ }
1479+
1480+ [ Fact ]
1481+ public void ParseBuildOutput_WithRelativeProjectPath_PreservesAsIs ( )
1482+ {
1483+ var result = ErrorResultFactory . ParseBuildOutput (
1484+ "Command: dotnet build\n Build succeeded.\n Exit Code: 0" ,
1485+ project : "src/MyApp.csproj" ) ;
1486+
1487+ Assert . Equal ( "src/MyApp.csproj" , result . Project ) ;
1488+ }
1489+
1490+ #endregion
1491+
1492+ #region ErrorResult File/Line/Column Tests
1493+
1494+ [ Fact ]
1495+ public void CreateResult_WithCompilerError_PopulatesFileLineColumn ( )
1496+ {
1497+ // Arrange
1498+ var output = "Program.cs(9,51): error CS0246: The type or namespace name 'IRenderable' could not be found" ;
1499+ var error = "" ;
1500+ var exitCode = 1 ;
1501+
1502+ // Act
1503+ var result = ErrorResultFactory . CreateResult ( output , error , exitCode ) ;
1504+
1505+ // Assert
1506+ var errorResponse = Assert . IsType < ErrorResponse > ( result ) ;
1507+ var parsedError = Assert . Single ( errorResponse . Errors ) ;
1508+ Assert . Equal ( "CS0246" , parsedError . Code ) ;
1509+ Assert . Contains ( "Program.cs" , parsedError . File ) ;
1510+ Assert . Equal ( 9 , parsedError . Line ) ;
1511+ Assert . Equal ( 51 , parsedError . Column ) ;
1512+ }
1513+
1514+ #endregion
13501515}
13511516
0 commit comments