diff --git a/docs/CHANGELOG-v3.md b/docs/CHANGELOG-v3.md index 45b31b69da..88fe3857a2 100644 --- a/docs/CHANGELOG-v3.md +++ b/docs/CHANGELOG-v3.md @@ -42,6 +42,8 @@ What's changed since pre-release v3.0.0-B0351: [#1842](https://github.com/microsoft/PSRule/issues/1842) - Fixed duplicate reasons are reported for the same rule by @BernieWhite. [#2553](https://github.com/microsoft/PSRule/issues/2553) + - Fixed JSON output format returns exception when no results are produced by @BernieWhite. + [#1832](https://github.com/microsoft/PSRule/issues/1832) ## v3.0.0-B0351 (pre-release) diff --git a/src/PSRule/Pipeline/Output/JsonOutputWriter.cs b/src/PSRule/Pipeline/Output/JsonOutputWriter.cs index 5e417e4e7c..92cd9a0017 100644 --- a/src/PSRule/Pipeline/Output/JsonOutputWriter.cs +++ b/src/PSRule/Pipeline/Output/JsonOutputWriter.cs @@ -8,8 +8,12 @@ namespace PSRule.Pipeline.Output; +#nullable enable + internal sealed class JsonOutputWriter : SerializationOutputWriter { + private const string EMPTY_ARRAY = "[]"; + internal JsonOutputWriter(PipelineWriter inner, PSRuleOption option, ShouldProcess shouldProcess) : base(inner, option, shouldProcess) { } @@ -20,6 +24,9 @@ protected override string Serialize(object[] o) internal static string ToJson(object[] o, int? jsonIndent) { + if (o == null || o.Length == 0) + return EMPTY_ARRAY; + using var stringWriter = new StringWriter(); using var jsonTextWriter = new JsonCommentWriter(stringWriter); @@ -56,3 +63,5 @@ internal static string ToJson(object[] o, int? jsonIndent) return stringWriter.ToString(); } } + +#nullable restore diff --git a/src/PSRule/Pipeline/Output/YamlOutputWriter.cs b/src/PSRule/Pipeline/Output/YamlOutputWriter.cs index 84fadb7e87..2c515a0a4d 100644 --- a/src/PSRule/Pipeline/Output/YamlOutputWriter.cs +++ b/src/PSRule/Pipeline/Output/YamlOutputWriter.cs @@ -11,6 +11,8 @@ namespace PSRule.Pipeline.Output; +#nullable enable + internal sealed class YamlOutputWriter : SerializationOutputWriter { internal YamlOutputWriter(PipelineWriter inner, PSRuleOption option, ShouldProcess shouldProcess) @@ -18,6 +20,9 @@ internal YamlOutputWriter(PipelineWriter inner, PSRuleOption option, ShouldProce protected override string Serialize(object[] o) { + if (o == null || o.Length == 0) + return string.Empty; + return o[0] is IEnumerable baselines ? ToBaselineYaml(baselines) : ToYaml(o); } @@ -57,3 +62,5 @@ internal static string ToBaselineYaml(IEnumerable baselines) return output.ToString(); } } + +#nullable restore diff --git a/tests/PSRule.Tests/Pipeline/Output/JsonOutputWriterTests.cs b/tests/PSRule.Tests/Pipeline/Output/JsonOutputWriterTests.cs index 24e683126e..9833b3de6d 100644 --- a/tests/PSRule.Tests/Pipeline/Output/JsonOutputWriterTests.cs +++ b/tests/PSRule.Tests/Pipeline/Output/JsonOutputWriterTests.cs @@ -12,17 +12,17 @@ namespace PSRule.Pipeline.Output; public sealed class JsonOutputWriterTests : OutputWriterBaseTests { [Fact] - public void Json() + public void Output_WithIndent_ShouldReturnIndentedResults() { var option = GetOption(); option.Output.JsonIndent = 2; - option.Repository.Url = "https://github.com/microsoft/PSRule.UnitTest"; var output = new TestWriter(option); var result = new InvokeResult(GetRun()); result.Add(GetPass()); result.Add(GetFail()); result.Add(GetFail("rid-003", SeverityLevel.Warning)); result.Add(GetFail("rid-004", SeverityLevel.Information)); + var writer = new JsonOutputWriter(output, option, null); writer.Begin(); writer.WriteObject(result, false); @@ -132,4 +132,20 @@ public void Json() } ]", output.Output.OfType().FirstOrDefault()); } + + [Fact] + public void Output_WithNoRecords_ShouldReturnEmptyArray() + { + var option = GetOption(); + option.Output.JsonIndent = 2; + var output = new TestWriter(option); + var result = new InvokeResult(GetRun()); + var writer = new JsonOutputWriter(output, option, null); + + writer.Begin(); + writer.WriteObject(result, false); + writer.End(new DefaultPipelineResult(null, Options.BreakLevel.None)); + + Assert.Equal("[]", output.Output.OfType().FirstOrDefault()); + } } diff --git a/tests/PSRule.Tests/Pipeline/Output/YamlOutputWriterTests.cs b/tests/PSRule.Tests/Pipeline/Output/YamlOutputWriterTests.cs index 686a76d41e..bdd78c1cdc 100644 --- a/tests/PSRule.Tests/Pipeline/Output/YamlOutputWriterTests.cs +++ b/tests/PSRule.Tests/Pipeline/Output/YamlOutputWriterTests.cs @@ -11,12 +11,10 @@ namespace PSRule.Pipeline.Output; /// public sealed class YamlOutputWriterTests : OutputWriterBaseTests { - [Fact] - public void Yaml() + public void Output_WithIndent_ShouldReturnResults() { var option = GetOption(); - option.Repository.Url = "https://github.com/microsoft/PSRule.UnitTest"; var output = new TestWriter(option); var result = new InvokeResult(GetRun()); result.Add(GetPass()); @@ -109,4 +107,18 @@ over two lines. ", output.Output.OfType().FirstOrDefault()); } + [Fact] + public void Output_WithNoRecords_ShouldReturnSuccessfully() + { + var option = GetOption(); + var output = new TestWriter(option); + var result = new InvokeResult(GetRun()); + var writer = new YamlOutputWriter(output, option, null); + + writer.Begin(); + writer.WriteObject(result, false); + writer.End(new DefaultPipelineResult(null, Options.BreakLevel.None)); + + Assert.Empty(output.Output.OfType().FirstOrDefault()); + } }