// Copyright (c) Microsoft. All rights reserved. using System; using System.Collections; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using Microsoft.Agents.AI.Workflows.Declarative.Extensions; using Microsoft.Agents.AI.Workflows.Declarative.Kit; using Microsoft.Agents.ObjectModel; using Microsoft.PowerFx.Types; namespace Microsoft.Agents.AI.Workflows.Declarative.UnitTests.Extensions; public sealed class DataValueExtensionsTests { [Fact] public void ToDataValueWithNull() { // Arrange object? value = null; // Act DataValue result = value.ToDataValue(); // Assert Assert.IsType(result); } [Fact] public void ToDataValueWithUnassignedValue() { // Arrange object value = UnassignedValue.Instance; // Act DataValue result = value.ToDataValue(); // Assert Assert.IsType(result); } [Fact] public void ToDataValueWithBooleanTrue() { // Arrange const bool Value = true; // Act DataValue result = Value.ToDataValue(); // Assert BooleanDataValue boolValue = Assert.IsType(result); Assert.True(boolValue.Value); } [Fact] public void ToDataValueWithBooleanFalse() { // Arrange const bool Value = false; // Act DataValue result = Value.ToDataValue(); // Assert BooleanDataValue boolValue = Assert.IsType(result); Assert.False(boolValue.Value); } [Fact] public void ToDataValueWithInt() { // Arrange const int Value = 42; // Act DataValue result = Value.ToDataValue(); // Assert NumberDataValue numberValue = Assert.IsType(result); Assert.Equal(42, numberValue.Value); } [Fact] public void ToDataValueWithLong() { // Arrange const long Value = 9876543210L; // Act DataValue result = Value.ToDataValue(); // Assert NumberDataValue numberValue = Assert.IsType(result); Assert.Equal(9876543210L, numberValue.Value); } [Fact] public void ToDataValueWithFloat() { // Arrange const float Value = 3.14f; // Act DataValue result = Value.ToDataValue(); // Assert FloatDataValue floatValue = Assert.IsType(result); Assert.Equal(3.14f, floatValue.Value, precision: 2); } [Fact] public void ToDataValueWithDecimal() { // Arrange const decimal Value = 123.456m; // Act DataValue result = Value.ToDataValue(); // Assert NumberDataValue numberValue = Assert.IsType(result); Assert.Equal(123.456m, numberValue.Value); } [Fact] public void ToDataValueWithDouble() { // Arrange const double Value = 2.71828; // Act DataValue result = Value.ToDataValue(); // Assert FloatDataValue floatValue = Assert.IsType(result); Assert.Equal(2.71828, floatValue.Value, precision: 5); } [Fact] public void ToDataValueWithString() { // Arrange const string Value = "Test String"; // Act DataValue result = Value.ToDataValue(); // Assert StringDataValue stringValue = Assert.IsType(result); Assert.Equal("Test String", stringValue.Value); } [Fact] public void ToDataValueWithDateTimeZeroTime() { // Arrange DateTime value = new(2025, 10, 17, 0, 0, 0); // Act DataValue result = value.ToDataValue(); // Assert DateDataValue dateValue = Assert.IsType(result); Assert.Equal(new DateTime(2025, 10, 17), dateValue.Value); } [Fact] public void ToDataValueWithDateTimeNonZeroTime() { // Arrange DateTime value = new(2025, 10, 17, 14, 30, 45); // Act DataValue result = value.ToDataValue(); // Assert DateTimeDataValue dateTimeValue = Assert.IsType(result); Assert.Equal(new DateTime(2025, 10, 17, 14, 30, 45), dateTimeValue.Value.DateTime); } [Fact] public void ToDataValueWithTimeSpan() { // Arrange TimeSpan value = TimeSpan.FromHours(2.5); // Act DataValue result = value.ToDataValue(); // Assert TimeDataValue timeValue = Assert.IsType(result); Assert.Equal(TimeSpan.FromHours(2.5), timeValue.Value); } [Fact] public void ToDataValueWithDataValue() { // Arrange DataValue value = StringDataValue.Create("Already a DataValue"); // Act DataValue result = value.ToDataValue(); // Assert Assert.Same(value, result); } [Fact] public void ToDataValueWithFormulaValue() { // Arrange FormulaValue value = FormulaValue.New(123); // Act DataValue result = value.ToDataValue(); // Assert NumberDataValue numberValue = Assert.IsType(result); Assert.Equal(123, numberValue.Value); } [Fact] public void ToFormulaWithNull() { // Arrange DataValue? value = null; // Act FormulaValue result = value.ToFormula(); // Assert Assert.IsType(result); } [Fact] public void ToFormulaWithBlankDataValue() { // Arrange DataValue value = DataValue.Blank(); // Act FormulaValue result = value.ToFormula(); // Assert Assert.IsType(result); } [Fact] public void ToFormulaWithBooleanDataValue() { // Arrange DataValue value = BooleanDataValue.Create(true); // Act FormulaValue result = value.ToFormula(); // Assert BooleanValue boolValue = Assert.IsType(result); Assert.True(boolValue.Value); } [Fact] public void ToFormulaWithNumberDataValue() { // Arrange DataValue value = NumberDataValue.Create(99.5m); // Act FormulaValue result = value.ToFormula(); // Assert DecimalValue decimalValue = Assert.IsType(result); Assert.Equal(99.5m, decimalValue.Value); } [Fact] public void ToFormulaWithFloatDataValue() { // Arrange DataValue value = FloatDataValue.Create(1.23); // Act FormulaValue result = value.ToFormula(); // Assert NumberValue numberValue = Assert.IsType(result); Assert.Equal(1.23, numberValue.Value, precision: 2); } [Fact] public void ToFormulaWithStringDataValue() { // Arrange DataValue value = StringDataValue.Create("Test"); // Act FormulaValue result = value.ToFormula(); // Assert StringValue stringValue = Assert.IsType(result); Assert.Equal("Test", stringValue.Value); } [Fact] public void ToFormulaWithDateTimeDataValue() { // Arrange DateTime dateTime = new(2025, 10, 17, 12, 0, 0); DataValue value = DateTimeDataValue.Create(dateTime); // Act FormulaValue result = value.ToFormula(); // Assert DateTimeValue dateTimeValue = Assert.IsType(result); Assert.Equal(dateTime, dateTimeValue.GetConvertedValue(TimeZoneInfo.Utc)); } [Fact] public void ToFormulaWithDateDataValue() { // Arrange DateTime date = new(2025, 10, 17); DataValue value = DateDataValue.Create(date); // Act FormulaValue result = value.ToFormula(); // Assert DateValue dateValue = Assert.IsType(result); Assert.Equal(date, dateValue.GetConvertedValue(TimeZoneInfo.Utc)); } [Fact] public void ToFormulaWithTimeDataValue() { // Arrange TimeSpan time = TimeSpan.FromHours(3); DataValue value = TimeDataValue.Create(time); // Act FormulaValue result = value.ToFormula(); // Assert TimeValue timeValue = Assert.IsType(result); Assert.Equal(time, timeValue.Value); } [Fact] public void ToFormulaWithRecordDataValue() { // Arrange DataValue value = DataValue.RecordFromFields( new KeyValuePair("Name", StringDataValue.Create("John")), new KeyValuePair("Age", NumberDataValue.Create(30))); // Act FormulaValue result = value.ToFormula(); // Assert RecordValue recordValue = Assert.IsType(result, exactMatch: false); Assert.Equal(2, recordValue.Fields.Count()); } [Fact] public void ToFormulaWithTableDataValue() { // Arrange RecordDataValue record = DataValue.RecordFromFields( new KeyValuePair("Field", StringDataValue.Create("Value"))); DataValue value = DataValue.TableFromRecords(ImmutableArray.Create(record)); // Act FormulaValue result = value.ToFormula(); // Assert TableValue tableValue = Assert.IsType(result, exactMatch: false); Assert.Single(tableValue.Rows); } [Fact] public void ToFormulaTypeWithNull() { // Arrange DataValue? value = null; // Act FormulaType result = value.ToFormulaType(); // Assert Assert.Equal(FormulaType.Blank, result); } [Fact] public void ToFormulaTypeWithBooleanDataValue() { // Arrange DataValue value = BooleanDataValue.Create(true); // Act FormulaType result = value.ToFormulaType(); // Assert Assert.Equal(FormulaType.Boolean, result); } [Fact] public void ToFormulaTypeWithStringDataValue() { // Arrange DataValue value = StringDataValue.Create("Test"); // Act FormulaType result = value.ToFormulaType(); // Assert Assert.Equal(FormulaType.String, result); } [Fact] public void DataTypeToFormulaTypeWithNull() { // Arrange DataType? type = null; // Act FormulaType result = type.ToFormulaType(); // Assert Assert.Equal(FormulaType.Blank, result); } [Fact] public void DataTypeToFormulaTypeWithBooleanDataType() { // Arrange DataType type = BooleanDataType.Instance; // Act FormulaType result = type.ToFormulaType(); // Assert Assert.Equal(FormulaType.Boolean, result); } [Fact] public void DataTypeToFormulaTypeWithNumberDataType() { // Arrange DataType type = NumberDataType.Instance; // Act FormulaType result = type.ToFormulaType(); // Assert Assert.Equal(FormulaType.Decimal, result); } [Fact] public void DataTypeToFormulaTypeWithFloatDataType() { // Arrange DataType type = FloatDataType.Instance; // Act FormulaType result = type.ToFormulaType(); // Assert Assert.Equal(FormulaType.Number, result); } [Fact] public void DataTypeToFormulaTypeWithStringDataType() { // Arrange DataType type = StringDataType.Instance; // Act FormulaType result = type.ToFormulaType(); // Assert Assert.Equal(FormulaType.String, result); } [Fact] public void DataTypeToFormulaTypeWithDateTimeDataType() { // Arrange DataType type = DateTimeDataType.Instance; // Act FormulaType result = type.ToFormulaType(); // Assert Assert.Equal(FormulaType.DateTime, result); } [Fact] public void DataTypeToFormulaTypeWithDateDataType() { // Arrange DataType type = DateDataType.Instance; // Act FormulaType result = type.ToFormulaType(); // Assert Assert.Equal(FormulaType.Date, result); } [Fact] public void DataTypeToFormulaTypeWithTimeDataType() { // Arrange DataType type = TimeDataType.Instance; // Act FormulaType result = type.ToFormulaType(); // Assert Assert.Equal(FormulaType.Time, result); } [Fact] public void ToObjectWithNull() { // Arrange DataValue? value = null; // Act object? result = value.ToObject(); // Assert Assert.Null(result); } [Fact] public void ToObjectWithBlankDataValue() { // Arrange DataValue value = DataValue.Blank(); // Act object? result = value.ToObject(); // Assert Assert.Null(result); } [Fact] public void ToObjectWithBooleanDataValue() { // Arrange DataValue value = BooleanDataValue.Create(true); // Act object? result = value.ToObject(); // Assert Assert.IsType(result); Assert.True((bool)result); } [Fact] public void ToObjectWithNumberDataValue() { // Arrange DataValue value = NumberDataValue.Create(42.5m); // Act object? result = value.ToObject(); // Assert Assert.IsType(result); Assert.Equal(42.5m, (decimal)result); } [Fact] public void ToObjectWithStringDataValue() { // Arrange DataValue value = StringDataValue.Create("Hello"); // Act object? result = value.ToObject(); // Assert Assert.IsType(result); Assert.Equal("Hello", (string)result); } [Fact] public void ToClrTypeWithBooleanDataType() { // Arrange DataType type = BooleanDataType.Instance; // Act Type result = type.ToClrType(); // Assert Assert.Equal(typeof(bool), result); } [Fact] public void ToClrTypeWithNumberDataType() { // Arrange DataType type = NumberDataType.Instance; // Act Type result = type.ToClrType(); // Assert Assert.Equal(typeof(decimal), result); } [Fact] public void ToClrTypeWithFloatDataType() { // Arrange DataType type = FloatDataType.Instance; // Act Type result = type.ToClrType(); // Assert Assert.Equal(typeof(double), result); } [Fact] public void ToClrTypeWithStringDataType() { // Arrange DataType type = StringDataType.Instance; // Act Type result = type.ToClrType(); // Assert Assert.Equal(typeof(string), result); } [Fact] public void ToClrTypeWithDateTimeDataType() { // Arrange DataType type = DateTimeDataType.Instance; // Act Type result = type.ToClrType(); // Assert Assert.Equal(typeof(DateTime), result); } [Fact] public void ToClrTypeWithTimeDataType() { // Arrange DataType type = TimeDataType.Instance; // Act Type result = type.ToClrType(); // Assert Assert.Equal(typeof(TimeSpan), result); } [Fact] public void AsListWithNull() { // Arrange DataValue? value = null; // Act IList? result = value.AsList(); // Assert Assert.Null(result); } [Fact] public void AsListWithBlankDataValue() { // Arrange DataValue value = DataValue.Blank(); // Act IList? result = value.AsList(); // Assert Assert.Null(result); } [Fact] public void NewBlankWithNullDataType() { // Arrange DataType? type = null; // Act FormulaValue result = type.NewBlank(); // Assert Assert.IsType(result); } [Fact] public void NewBlankWithBooleanDataType() { // Arrange DataType type = BooleanDataType.Instance; // Act FormulaValue result = type.NewBlank(); // Assert Assert.IsType(result); } [Fact] public void ToRecordValueWithRecordDataValue() { // Arrange RecordDataValue recordDataValue = DataValue.RecordFromFields( new KeyValuePair("Field1", StringDataValue.Create("Value1")), new KeyValuePair("Field2", NumberDataValue.Create(123))); // Act RecordValue result = recordDataValue.ToRecordValue(); // Assert Assert.NotNull(result); Assert.Equal(2, result.Fields.Count()); Assert.NotNull(result.GetField("Field1")); Assert.NotNull(result.GetField("Field2")); } [Fact] public void ToRecordTypeWithRecordDataType() { // Arrange RecordDataType recordDataType = new RecordDataType.Builder { Properties = { ["Name"] = new PropertyInfo.Builder { Type = StringDataType.Instance }.Build(), ["Count"] = new PropertyInfo.Builder { Type = NumberDataType.Instance }.Build() } }.Build(); // Act RecordType result = recordDataType.ToRecordType(); // Assert Assert.NotNull(result); IEnumerable fieldTypes = result.GetFieldTypes(); List fieldTypesList = fieldTypes.ToList(); Assert.Equal(2, fieldTypesList.Count); IEnumerable fieldNames = fieldTypesList.Select(f => f.Name.Value); Assert.Contains("Name", fieldNames); Assert.Contains("Count", fieldNames); NamedFormulaType nameField = fieldTypesList.First(f => f.Name.Value == "Name"); NamedFormulaType countField = fieldTypesList.First(f => f.Name.Value == "Count"); Assert.Equal(FormulaType.String, nameField.Type); Assert.Equal(FormulaType.Decimal, countField.Type); } [Fact] public void ToRecordValueWithDictionary() { // Arrange IDictionary dictionary = new Dictionary { ["Key1"] = "Value1", ["Key2"] = 42 }; // Act RecordDataValue result = dictionary.ToRecordValue(); // Assert Assert.NotNull(result); Assert.Equal(2, result.Properties.Count); Assert.True(result.Properties.ContainsKey("Key1")); Assert.True(result.Properties.ContainsKey("Key2")); } [Fact] public void ToTableValueWithEmptyEnumerable() { // Arrange IEnumerable enumerable = Array.Empty(); // Act TableDataValue result = enumerable.ToTableValue(); // Assert Assert.NotNull(result); Assert.Empty(result.Values); } [Fact] public void ToTableValueWithDictionaryEnumerable() { // Arrange IEnumerable enumerable = new List { new Dictionary { ["Name"] = "Alice", ["Age"] = 30 }, new Dictionary { ["Name"] = "Bob", ["Age"] = 25 } }; // Act TableDataValue result = enumerable.ToTableValue(); // Assert Assert.NotNull(result); } [Fact] public void ToTableValueWithPrimitiveEnumerable() { // Arrange IEnumerable enumerable = new List { 1, 2, 3 }; // Act TableDataValue result = enumerable.ToTableValue(); // Assert Assert.NotNull(result); Assert.Equal(3, result.Values.Length); } }