using ClaudeDo.Worker.Runner; namespace ClaudeDo.Worker.Tests.Runner; public sealed class StreamAnalyzerTests { [Fact] public void Extracts_Result_Markdown() { var analyzer = new StreamAnalyzer(); analyzer.ProcessLine("""{"type":"result","result":"## Done","session_id":"sess-1"}"""); var result = analyzer.GetResult(); Assert.Equal("## Done", result.ResultMarkdown); Assert.Equal("sess-1", result.SessionId); } [Fact] public void Extracts_Structured_Output() { var analyzer = new StreamAnalyzer(); analyzer.ProcessLine("""{"type":"result","result":"ok","structured_output":{"summary":"all good"},"session_id":"s1"}"""); var result = analyzer.GetResult(); Assert.Equal("ok", result.ResultMarkdown); Assert.Contains("all good", result.StructuredOutputJson); } [Fact] public void Counts_Assistant_Turns() { var analyzer = new StreamAnalyzer(); analyzer.ProcessLine("""{"type":"assistant","message":"hi"}"""); analyzer.ProcessLine("""{"type":"assistant","message":"working on it"}"""); analyzer.ProcessLine("""{"type":"result","result":"done","session_id":"s1"}"""); var result = analyzer.GetResult(); Assert.Equal(2, result.TurnCount); } [Fact] public void Accumulates_Token_Usage() { var analyzer = new StreamAnalyzer(); analyzer.ProcessLine("""{"type":"stream_event","event":{"type":"message_start","message":{"usage":{"input_tokens":100,"output_tokens":50}}}}"""); analyzer.ProcessLine("""{"type":"stream_event","event":{"type":"message_start","message":{"usage":{"input_tokens":200,"output_tokens":80}}}}"""); analyzer.ProcessLine("""{"type":"result","result":"done","session_id":"s1"}"""); var result = analyzer.GetResult(); Assert.Equal(300, result.TokensIn); Assert.Equal(130, result.TokensOut); } [Fact] public void Counts_Api_Retry_Events() { var analyzer = new StreamAnalyzer(); analyzer.ProcessLine("""{"type":"system","subtype":"api_retry","attempt":1,"error":"rate_limit"}"""); analyzer.ProcessLine("""{"type":"system","subtype":"api_retry","attempt":2,"error":"rate_limit"}"""); analyzer.ProcessLine("""{"type":"result","result":"done","session_id":"s1"}"""); var result = analyzer.GetResult(); Assert.Equal(2, result.ApiRetryCount); } [Fact] public void Malformed_Json_Is_Ignored() { var analyzer = new StreamAnalyzer(); analyzer.ProcessLine("not json {{{"); analyzer.ProcessLine(""); analyzer.ProcessLine(" "); var result = analyzer.GetResult(); Assert.Null(result.ResultMarkdown); Assert.Equal(0, result.TurnCount); } [Fact] public void No_Result_Event_Returns_Null_Fields() { var analyzer = new StreamAnalyzer(); analyzer.ProcessLine("""{"type":"assistant","message":"hi"}"""); var result = analyzer.GetResult(); Assert.Null(result.ResultMarkdown); Assert.Null(result.SessionId); } }