using EnvelopeRenderer.Desktop.Core.Launch; namespace EnvelopeRenderer.Desktop.Tests; public class ProgressEventParserTests { [Fact] public void TryParse_StartupLine_ParsesFields() { var parsed = ProgressEventParser.TryParse("PROGRESS startup elapsedMs=0 completed=0", out var progressEvent); Assert.True(parsed); Assert.Equal(ProgressEventKind.Startup, progressEvent!.Kind); Assert.Equal(0, progressEvent.ElapsedMs); Assert.Equal(0, progressEvent.Completed); Assert.Null(progressEvent.Reason); } [Fact] public void TryParse_RenderLine_ParsesFields() { var parsed = ProgressEventParser.TryParse("PROGRESS render elapsedMs=802 completed=1", out var progressEvent); Assert.True(parsed); Assert.Equal(ProgressEventKind.Render, progressEvent!.Kind); Assert.Equal(802, progressEvent.ElapsedMs); Assert.Equal(1, progressEvent.Completed); Assert.Null(progressEvent.Reason); } [Fact] public void TryParse_CompleteLine_ParsesFields() { var parsed = ProgressEventParser.TryParse("PROGRESS complete elapsedMs=1900 completed=392", out var progressEvent); Assert.True(parsed); Assert.Equal(ProgressEventKind.Complete, progressEvent!.Kind); Assert.Equal(1900, progressEvent.ElapsedMs); Assert.Equal(392, progressEvent.Completed); Assert.Null(progressEvent.Reason); } [Fact] public void TryParse_FailureLine_CapturesReasonToEndOfLineVerbatim() { const string line = "PROGRESS failure elapsedMs=1805 completed=392 reason=Failed to save PDF to 'out.pdf' (error code 999)."; var parsed = ProgressEventParser.TryParse(line, out var progressEvent); Assert.True(parsed); Assert.Equal(ProgressEventKind.Failure, progressEvent!.Kind); Assert.Equal(1805, progressEvent.ElapsedMs); Assert.Equal(392, progressEvent.Completed); Assert.Equal("Failed to save PDF to 'out.pdf' (error code 999).", progressEvent.Reason); } [Fact] public void TryParse_ReasonContainingSpaces_KeepsWholeReasonTogether() { const string line = "PROGRESS failure elapsedMs=5 completed=0 reason=multiple words here"; var parsed = ProgressEventParser.TryParse(line, out var progressEvent); Assert.True(parsed); Assert.Equal("multiple words here", progressEvent!.Reason); } [Theory] [InlineData(null)] [InlineData("")] [InlineData(" ")] [InlineData("not a progress line")] [InlineData("PROGRESS")] [InlineData("PROGRESS startup")] [InlineData("PROGRESS unknownkind elapsedMs=0 completed=0")] [InlineData("PROGRESS startup notElapsed=0 completed=0")] [InlineData("PROGRESS startup elapsedMs=abc completed=0")] [InlineData("PROGRESS startup elapsedMs=0 notCompleted=0")] [InlineData("PROGRESS startup elapsedMs=0 completed=abc")] [InlineData("PROGRESS startup elapsedMs=0 completed=0 notreason=x")] public void TryParse_MalformedOrUnrelatedLine_ReturnsFalseAndNullEvent(string? line) { var parsed = ProgressEventParser.TryParse(line, out var progressEvent); Assert.False(parsed); Assert.Null(progressEvent); } }