File: SpeechToText\SpeechToTextResponseTests.cs
Web Access
Project: src\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;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using Xunit;
 
namespace Microsoft.Extensions.AI;
 
public class SpeechToTextResponseTests
{
    [Fact]
    public void Constructor_InvalidArgs_Throws()
    {
        Assert.Throws<ArgumentNullException>("contents", () => new SpeechToTextResponse((IList<AIContent>)null!));
    }
 
    [Fact]
    public void Constructor_Parameterless_PropsDefaulted()
    {
        SpeechToTextResponse response = new();
        Assert.Empty(response.Contents);
        Assert.Empty(response.Text);
        Assert.NotNull(response.Contents);
        Assert.Same(response.Contents, response.Contents);
        Assert.Empty(response.Contents);
        Assert.Null(response.RawRepresentation);
        Assert.Null(response.AdditionalProperties);
        Assert.Null(response.StartTime);
        Assert.Null(response.EndTime);
        Assert.Equal(string.Empty, response.ToString());
    }
 
    [Theory]
    [InlineData(null)]
    [InlineData("text")]
    public void Constructor_String_PropsRoundtrip(string? text)
    {
        SpeechToTextResponse response = new(text);
 
        Assert.Same(response.Contents, response.Contents);
        if (text is null)
        {
            Assert.Empty(response.Contents);
        }
        else
        {
            Assert.Single(response.Contents);
            TextContent tc = Assert.IsType<TextContent>(response.Contents[0]);
            Assert.Equal(text, tc.Text);
        }
 
        Assert.Null(response.RawRepresentation);
        Assert.Null(response.AdditionalProperties);
        Assert.Equal(text ?? string.Empty, response.ToString());
    }
 
    [Fact]
    public void Constructor_List_InvalidArgs_Throws()
    {
        Assert.Throws<ArgumentNullException>("contents", () => new SpeechToTextResponse((IList<AIContent>)null!));
    }
 
    [Theory]
    [InlineData(0)]
    [InlineData(1)]
    [InlineData(2)]
    public void Constructor_List_PropsRoundtrip(int contentCount)
    {
        List<AIContent> content = [];
        for (int i = 0; i < contentCount; i++)
        {
            content.Add(new TextContent($"text-{i}"));
        }
 
        SpeechToTextResponse response = new(content);
 
        Assert.Same(response.Contents, response.Contents);
        if (contentCount == 0)
        {
            Assert.Empty(response.Contents);
            Assert.Empty(response.Text);
        }
        else
        {
            Assert.Equal(contentCount, response.Contents.Count);
            for (int i = 0; i < contentCount; i++)
            {
                TextContent tc = Assert.IsType<TextContent>(response.Contents[i]);
                Assert.Equal($"text-{i}", tc.Text);
            }
 
            Assert.Equal(string.Concat(Enumerable.Range(0, contentCount).Select(i => $"text-{i}")), response.Text);
            Assert.Equal(string.Concat(Enumerable.Range(0, contentCount).Select(i => $"text-{i}")), response.ToString());
        }
    }
 
    [Fact]
    public void Properties_Roundtrip()
    {
        SpeechToTextResponse response = new();
        Assert.Null(response.ResponseId);
        response.ResponseId = "id";
        Assert.Equal("id", response.ResponseId);
 
        Assert.Null(response.ModelId);
        response.ModelId = "modelId";
        Assert.Equal("modelId", response.ModelId);
 
        Assert.Null(response.RawRepresentation);
        object raw = new();
        response.RawRepresentation = raw;
        Assert.Same(raw, response.RawRepresentation);
 
        Assert.Null(response.AdditionalProperties);
        AdditionalPropertiesDictionary additionalProps = [];
        response.AdditionalProperties = additionalProps;
        Assert.Same(additionalProps, response.AdditionalProperties);
 
        Assert.Null(response.StartTime);
        TimeSpan startTime = TimeSpan.FromSeconds(1);
        response.StartTime = startTime;
        Assert.Equal(startTime, response.StartTime);
 
        Assert.Null(response.EndTime);
        TimeSpan endTime = TimeSpan.FromSeconds(2);
        response.EndTime = endTime;
        Assert.Equal(endTime, response.EndTime);
 
        List<AIContent> newContents = [new TextContent("text1"), new TextContent("text2")];
        response.Contents = newContents;
        Assert.Same(newContents, response.Contents);
    }
 
    [Fact]
    public void JsonSerialization_Roundtrips()
    {
        SpeechToTextResponse original = new()
        {
            Contents =
            [
                new TextContent("Text1"),
                new TextContent("Text2"),
                new TextContent("Text3"),
                new TextContent("Text4"),
            ],
            ResponseId = "id",
            ModelId = "modelId",
            StartTime = TimeSpan.FromSeconds(1),
            EndTime = TimeSpan.FromSeconds(2),
            RawRepresentation = new(),
            AdditionalProperties = new() { ["key"] = "value" },
        };
 
        string json = JsonSerializer.Serialize(original, TestJsonSerializerContext.Default.SpeechToTextResponse);
 
        SpeechToTextResponse? result = JsonSerializer.Deserialize(json, TestJsonSerializerContext.Default.SpeechToTextResponse);
 
        Assert.NotNull(result);
        Assert.Equal(4, result.Contents.Count);
 
        for (int i = 0; i < original.Contents.Count; i++)
        {
            Assert.Equal($"Text{i + 1}", ((TextContent)result.Contents[i]).Text);
        }
 
        Assert.Equal("id", result.ResponseId);
        Assert.Equal("modelId", result.ModelId);
        Assert.Equal(TimeSpan.FromSeconds(1), result.StartTime);
        Assert.Equal(TimeSpan.FromSeconds(2), result.EndTime);
 
        Assert.NotNull(result.AdditionalProperties);
        Assert.Single(result.AdditionalProperties);
        Assert.True(result.AdditionalProperties.TryGetValue("key", out object? value));
        Assert.IsType<JsonElement>(value);
        Assert.Equal("value", ((JsonElement)value!).GetString());
    }
 
    [Fact]
    public void ToString_OutputsText()
    {
        SpeechToTextResponse response = new("This is a test." + Environment.NewLine + "It's multiple lines.");
        Assert.Equal("This is a test." + Environment.NewLine + "It's multiple lines.", response.ToString());
    }
 
    [Fact]
    public void ToSpeechToTextResponseUpdates_ReturnsExpectedUpdate()
    {
        // Arrange: create a response with contents
        SpeechToTextResponse response = new()
        {
            Contents =
            [
                new TextContent("Hello, "),
                new DataContent("data:image/png;base64,AQIDBA==", mediaType: "image/png"),
                new TextContent("world!")
            ],
            StartTime = TimeSpan.FromSeconds(1),
            EndTime = TimeSpan.FromSeconds(2),
            ResponseId = "12345",
            ModelId = "someModel",
            AdditionalProperties = new() { ["key1"] = "value1", ["key2"] = 42 },
        };
 
        // Act: convert to streaming updates
        SpeechToTextResponseUpdate[] updates = response.ToSpeechToTextResponseUpdates();
 
        // Assert: should be a single update with all properties
        Assert.Single(updates);
 
        SpeechToTextResponseUpdate update = updates[0];
        Assert.Equal("12345", update.ResponseId);
        Assert.Equal("someModel", update.ModelId);
        Assert.Equal(SpeechToTextResponseUpdateKind.TextUpdated, update.Kind);
        Assert.Equal(TimeSpan.FromSeconds(1), update.StartTime);
        Assert.Equal(TimeSpan.FromSeconds(2), update.EndTime);
 
        Assert.Equal(3, update.Contents.Count);
        Assert.Equal("Hello, ", Assert.IsType<TextContent>(update.Contents[0]).Text);
        Assert.Equal("image/png", Assert.IsType<DataContent>(update.Contents[1]).MediaType);
        Assert.Equal("world!", Assert.IsType<TextContent>(update.Contents[2]).Text);
 
        Assert.NotNull(update.AdditionalProperties);
        Assert.Equal("value1", update.AdditionalProperties["key1"]);
        Assert.Equal(42, update.AdditionalProperties["key2"]);
    }
}