File: Realtime\RealtimeServerMessageTests.cs
Project: ..\..\..\test\Libraries\Microsoft.Extensions.AI.Abstractions.Tests\Microsoft.Extensions.AI.Abstractions.Tests.csproj (Microsoft.Extensions.AI.Abstractions.Tests)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Collections.Generic;
using Xunit;
 
#pragma warning disable MEAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates.
 
namespace Microsoft.Extensions.AI;
 
public class RealtimeServerMessageTests
{
    [Fact]
    public void RealtimeServerMessage_DefaultProperties()
    {
        var message = new RealtimeServerMessage();
 
        Assert.Equal(default, message.Type);
        Assert.Null(message.MessageId);
        Assert.Null(message.RawRepresentation);
    }
 
    [Fact]
    public void RealtimeServerMessage_Properties_Roundtrip()
    {
        var rawObj = new object();
        var message = new RealtimeServerMessage
        {
            Type = RealtimeServerMessageType.ResponseDone,
            MessageId = "evt_001",
            RawRepresentation = rawObj,
        };
 
        Assert.Equal(RealtimeServerMessageType.ResponseDone, message.Type);
        Assert.Equal("evt_001", message.MessageId);
        Assert.Same(rawObj, message.RawRepresentation);
    }
 
    [Fact]
    public void ErrorMessage_Constructor_SetsType()
    {
        var message = new ErrorRealtimeServerMessage();
 
        Assert.Equal(RealtimeServerMessageType.Error, message.Type);
    }
 
    [Fact]
    public void ErrorMessage_DefaultProperties()
    {
        var message = new ErrorRealtimeServerMessage();
 
        Assert.Null(message.Error);
        Assert.Null(message.OriginatingMessageId);
    }
 
    [Fact]
    public void ErrorMessage_Properties_Roundtrip()
    {
        var error = new ErrorContent("Test error") { Details = "temperature" };
        var message = new ErrorRealtimeServerMessage
        {
            Error = error,
            OriginatingMessageId = "evt_bad",
            MessageId = "evt_err_1",
        };
 
        Assert.Same(error, message.Error);
        Assert.Equal("evt_bad", message.OriginatingMessageId);
        Assert.Equal("temperature", message.Error.Details);
        Assert.Equal("evt_err_1", message.MessageId);
        Assert.IsAssignableFrom<RealtimeServerMessage>(message);
    }
 
    [Fact]
    public void InputAudioTranscriptionMessage_Constructor_SetsType()
    {
        var message = new InputAudioTranscriptionRealtimeServerMessage(
            RealtimeServerMessageType.InputAudioTranscriptionCompleted);
 
        Assert.Equal(RealtimeServerMessageType.InputAudioTranscriptionCompleted, message.Type);
    }
 
    [Fact]
    public void InputAudioTranscriptionMessage_DefaultProperties()
    {
        var message = new InputAudioTranscriptionRealtimeServerMessage(
            RealtimeServerMessageType.InputAudioTranscriptionDelta);
 
        Assert.Null(message.ContentIndex);
        Assert.Null(message.ItemId);
        Assert.Null(message.Transcription);
        Assert.Null(message.Usage);
        Assert.Null(message.Error);
    }
 
    [Fact]
    public void InputAudioTranscriptionMessage_Properties_Roundtrip()
    {
        var usage = new UsageDetails { InputTokenCount = 10, OutputTokenCount = 20 };
        var error = new ErrorContent("transcription error");
 
        var message = new InputAudioTranscriptionRealtimeServerMessage(
            RealtimeServerMessageType.InputAudioTranscriptionCompleted)
        {
            ContentIndex = 0,
            ItemId = "item_audio_1",
            Transcription = "Hello world",
            Usage = usage,
            Error = error,
        };
 
        Assert.Equal(0, message.ContentIndex);
        Assert.Equal("item_audio_1", message.ItemId);
        Assert.Equal("Hello world", message.Transcription);
        Assert.Same(usage, message.Usage);
        Assert.Same(error, message.Error);
        Assert.IsAssignableFrom<RealtimeServerMessage>(message);
    }
 
    [Fact]
    public void OutputTextAudioMessage_Constructor_SetsType()
    {
        var message = new OutputTextAudioRealtimeServerMessage(RealtimeServerMessageType.OutputTextDelta);
 
        Assert.Equal(RealtimeServerMessageType.OutputTextDelta, message.Type);
    }
 
    [Fact]
    public void OutputTextAudioMessage_DefaultProperties()
    {
        var message = new OutputTextAudioRealtimeServerMessage(RealtimeServerMessageType.OutputTextDelta);
 
        Assert.Null(message.ContentIndex);
        Assert.Null(message.Text);
        Assert.Null(message.Audio);
        Assert.Null(message.ItemId);
        Assert.Null(message.OutputIndex);
        Assert.Null(message.ResponseId);
    }
 
    [Fact]
    public void OutputTextAudioMessage_Properties_Roundtrip()
    {
        var message = new OutputTextAudioRealtimeServerMessage(RealtimeServerMessageType.OutputTextDone)
        {
            ContentIndex = 0,
            Text = "Hello there!",
            ItemId = "item_text_1",
            OutputIndex = 0,
            ResponseId = "resp_1",
        };
 
        Assert.Equal(RealtimeServerMessageType.OutputTextDone, message.Type);
        Assert.Equal(0, message.ContentIndex);
        Assert.Equal("Hello there!", message.Text);
        Assert.Equal("item_text_1", message.ItemId);
        Assert.Equal(0, message.OutputIndex);
        Assert.Equal("resp_1", message.ResponseId);
        Assert.IsAssignableFrom<RealtimeServerMessage>(message);
    }
 
    [Fact]
    public void ResponseCreatedMessage_Constructor_SetsType()
    {
        var message = new ResponseCreatedRealtimeServerMessage(RealtimeServerMessageType.ResponseCreated);
 
        Assert.Equal(RealtimeServerMessageType.ResponseCreated, message.Type);
    }
 
    [Fact]
    public void ResponseCreatedMessage_DefaultProperties()
    {
        var message = new ResponseCreatedRealtimeServerMessage(RealtimeServerMessageType.ResponseDone);
 
        Assert.Null(message.OutputAudioOptions);
        Assert.Null(message.OutputVoice);
        Assert.Null(message.ResponseId);
        Assert.Null(message.MaxOutputTokens);
        Assert.Null(message.AdditionalProperties);
        Assert.Null(message.Items);
        Assert.Null(message.OutputModalities);
        Assert.Null(message.Status);
        Assert.Null(message.Error);
        Assert.Null(message.Usage);
    }
 
    [Fact]
    public void ResponseCreatedMessage_Properties_Roundtrip()
    {
        var audioFormat = new RealtimeAudioFormat("audio/pcm", 24000);
        var metadata = new AdditionalPropertiesDictionary { ["key"] = "value" };
        var items = new List<RealtimeConversationItem>
        {
            new RealtimeConversationItem([new TextContent("response")], "item_1"),
        };
        var modalities = new List<string> { "text" };
        var error = new ErrorContent("response error");
        var usage = new UsageDetails { InputTokenCount = 15, OutputTokenCount = 25, TotalTokenCount = 40 };
 
        var message = new ResponseCreatedRealtimeServerMessage(RealtimeServerMessageType.ResponseDone)
        {
            OutputAudioOptions = audioFormat,
            OutputVoice = "alloy",
            ResponseId = "resp_1",
            MaxOutputTokens = 1000,
            AdditionalProperties = metadata,
            Items = items,
            OutputModalities = modalities,
            Status = "completed",
            Error = error,
            Usage = usage,
        };
 
        Assert.Same(audioFormat, message.OutputAudioOptions);
        Assert.Equal("alloy", message.OutputVoice);
        Assert.Equal("resp_1", message.ResponseId);
        Assert.Equal(1000, message.MaxOutputTokens);
        Assert.Same(metadata, message.AdditionalProperties);
        Assert.Same(items, message.Items);
        Assert.Same(modalities, message.OutputModalities);
        Assert.Equal("completed", message.Status);
        Assert.Same(error, message.Error);
        Assert.Same(usage, message.Usage);
        Assert.IsAssignableFrom<RealtimeServerMessage>(message);
    }
 
    [Fact]
    public void ResponseOutputItemMessage_Constructor_SetsType()
    {
        var message = new ResponseOutputItemRealtimeServerMessage(RealtimeServerMessageType.ResponseOutputItemDone);
 
        Assert.Equal(RealtimeServerMessageType.ResponseOutputItemDone, message.Type);
    }
 
    [Fact]
    public void ResponseOutputItemMessage_DefaultProperties()
    {
        var message = new ResponseOutputItemRealtimeServerMessage(RealtimeServerMessageType.ResponseOutputItemAdded);
 
        Assert.Null(message.ResponseId);
        Assert.Null(message.OutputIndex);
        Assert.Null(message.Item);
    }
 
    [Fact]
    public void ResponseOutputItemMessage_Properties_Roundtrip()
    {
        var item = new RealtimeConversationItem([new TextContent("output")], "item_out_1", ChatRole.Assistant);
 
        var message = new ResponseOutputItemRealtimeServerMessage(RealtimeServerMessageType.ResponseOutputItemDone)
        {
            ResponseId = "resp_1",
            OutputIndex = 0,
            Item = item,
        };
 
        Assert.Equal("resp_1", message.ResponseId);
        Assert.Equal(0, message.OutputIndex);
        Assert.Same(item, message.Item);
        Assert.IsAssignableFrom<RealtimeServerMessage>(message);
    }
}