Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ internal sealed class EditTableExecutor(EditTable model, WorkflowFormulaState st
EvaluationResult<DataValue> addResult = this.Evaluator.GetValue(addItemValue);
RecordValue newRecord = BuildRecord(tableValue.Type.ToRecord(), addResult.Value.ToFormula());
await tableValue.AppendAsync(newRecord, cancellationToken).ConfigureAwait(false);
await this.AssignAsync(variablePath, newRecord, context).ConfigureAwait(false);
await this.AssignAsync(variablePath, tableValue, context).ConfigureAwait(false);
break;
case TableChangeType.Remove:
ValueExpression removeItemValue = Throw.IfNull(this.Model.Value, $"{nameof(this.Model)}.{nameof(this.Model.Value)}");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ internal sealed class EditTableV2Executor(EditTableV2 model, WorkflowFormulaStat
EvaluationResult<DataValue> expressionResult = this.Evaluator.GetValue(addItemValue);
RecordValue newRecord = BuildRecord(tableValue.Type.ToRecord(), expressionResult.Value.ToFormula());
await tableValue.AppendAsync(newRecord, cancellationToken).ConfigureAwait(false);
await this.AssignAsync(this.Model.ItemsVariable, newRecord, context).ConfigureAwait(false);
await this.AssignAsync(this.Model.ItemsVariable, tableValue, context).ConfigureAwait(false);
}
else if (changeType is ClearItemsOperation)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,44 @@ await this.ExecuteTestAsync(
changeType: TableChangeType.Add,
value: new RecordDataValue([new("id", new NumberDataValue(7))]));

// Verify the variable now contains the added record
// Verify the variable remains a table containing the added record
FormulaValue resultValue = this.State.Get("MyTable");
RecordValue resultRecord = Assert.IsAssignableFrom<RecordValue>(resultValue);
DecimalValue idValue = Assert.IsType<DecimalValue>(resultRecord.GetField("id"));
TableValue resultTable = Assert.IsAssignableFrom<TableValue>(resultValue);
Assert.Equal(2, resultTable.Rows.Count());
DecimalValue idValue = Assert.IsType<DecimalValue>(resultTable.Rows.Last().Value.GetField("id"));
Assert.Equal(7, idValue.Value);
}

[Fact]
public async Task ConsecutiveAddsPreserveTableAsync()
{
// Arrange
FormulaValue tableValue = this.State.Engine.Eval("[{id: 1}]");
this.State.Set("MyTable", tableValue);

EditTable firstAdd = this.CreateModel(
nameof(ConsecutiveAddsPreserveTableAsync),
"MyTable",
TableChangeType.Add,
new RecordDataValue([new("id", new NumberDataValue(2))]));
EditTable secondAdd = this.CreateModel(
nameof(ConsecutiveAddsPreserveTableAsync),
"MyTable",
TableChangeType.Add,
new RecordDataValue([new("id", new NumberDataValue(3))]));

// Act
await this.ExecuteAsync(new EditTableExecutor(firstAdd, this.State));
await this.ExecuteAsync(new EditTableExecutor(secondAdd, this.State));

// Assert
TableValue resultTable = Assert.IsAssignableFrom<TableValue>(this.State.Get("MyTable"));
decimal[] ids = resultTable.Rows
.Select(row => Assert.IsType<DecimalValue>(row.Value.GetField("id")).Value)
.ToArray();
Assert.Equal([1, 2, 3], ids);
}

[Fact]
public async Task AddItemWithMultipleFieldsAsync()
{
Expand All @@ -57,9 +88,11 @@ await this.ExecuteTestAsync(
new("name", new StringDataValue("Second"))
]));

// Verify the variable now contains the added record
// Verify the variable remains a table containing the added record
FormulaValue resultValue = this.State.Get("MyTable");
RecordValue resultRecord = Assert.IsAssignableFrom<RecordValue>(resultValue);
TableValue resultTable = Assert.IsAssignableFrom<TableValue>(resultValue);
Assert.Equal(2, resultTable.Rows.Count());
RecordValue resultRecord = resultTable.Rows.Last().Value;
DecimalValue idValue = Assert.IsType<DecimalValue>(resultRecord.GetField("id"));
Assert.Equal(2, idValue.Value);
StringValue nameValue = Assert.IsType<StringValue>(resultRecord.GetField("name"));
Expand All @@ -83,9 +116,10 @@ await this.ExecuteTestAsync(
changeType: TableChangeType.Add,
value: new RecordDataValue([new("id", new NumberDataValue(1))]));

// Verify the variable now contains the added record
// Verify the variable remains a table containing the added record
FormulaValue resultValue = this.State.Get("MyTable");
RecordValue resultRecord = Assert.IsAssignableFrom<RecordValue>(resultValue);
TableValue resultTable = Assert.IsAssignableFrom<TableValue>(resultValue);
RecordValue resultRecord = Assert.Single(resultTable.Rows).Value;
DecimalValue idValue = Assert.IsType<DecimalValue>(resultRecord.GetField("id"));
Assert.Equal(1, idValue.Value);
}
Expand Down Expand Up @@ -345,11 +379,12 @@ public async Task AddWithExpressionAsync()
EditTableExecutor action = new(model, this.State);
await this.ExecuteAsync(action);

// Assert - Variable should contain the newly added record
// Assert - Variable should remain a table containing the newly added record
VerifyModel(model, action);
FormulaValue resultValue = this.State.Get("MyTable");
RecordValue resultRecord = Assert.IsAssignableFrom<RecordValue>(resultValue);
DecimalValue idValue = Assert.IsType<DecimalValue>(resultRecord.GetField("id"));
TableValue resultTable = Assert.IsAssignableFrom<TableValue>(resultValue);
Assert.Equal(2, resultTable.Rows.Count());
DecimalValue idValue = Assert.IsType<DecimalValue>(resultTable.Rows.Last().Value.GetField("id"));
Assert.Equal(10, idValue.Value);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft. All rights reserved.

using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Agents.AI.Workflows.Declarative.ObjectModel;
using Microsoft.Agents.ObjectModel;
Expand Down Expand Up @@ -144,7 +145,7 @@ public async Task AddItemOperationWithSingleFieldRecordAsync()
this.State.Set("TestTable", tableValue);

// Arrange, Act, Assert
await this.ExecuteTestAsync<RecordValue>(
await this.ExecuteTestAsync<TableValue>(
displayName: nameof(AddItemOperationWithSingleFieldRecordAsync),
variableName: "TestTable",
changeType: this.CreateAddItemOperation(new RecordDataValue.Builder
Expand All @@ -154,8 +155,8 @@ await this.ExecuteTestAsync<RecordValue>(
["Name"] = new StringDataValue("John")
}
}.Build()),
verifyAction: (variableName, recordValue) =>
Assert.Equal("John", recordValue.GetField("Name").ToObject())
verifyAction: (variableName, resultTable) =>
Assert.Equal("John", Assert.Single(resultTable.Rows).Value.GetField("Name").ToObject())
);
}

Expand All @@ -168,15 +169,46 @@ public async Task AddItemOperationWithScalarValueAsync()
this.State.Set("TestTable", tableValue);

// Act & Assert
await this.ExecuteTestAsync<RecordValue>(
await this.ExecuteTestAsync<TableValue>(
displayName: nameof(AddItemOperationWithScalarValueAsync),
variableName: "TestTable",
changeType: this.CreateAddItemOperation(new StringDataValue("TestValue")),
verifyAction: (variableName, recordValue) =>
Assert.Equal("TestValue", recordValue.GetField("Value").ToObject())
verifyAction: (variableName, resultTable) =>
Assert.Equal("TestValue", Assert.Single(resultTable.Rows).Value.GetField("Value").ToObject())
);
}

[Fact]
public async Task ConsecutiveAddItemOperationsPreserveTableAsync()
{
// Arrange
RecordType recordType = RecordType.Empty().Add("Value", FormulaType.String);
RecordValue initialRecord = FormulaValue.NewRecordFromFields(
recordType,
new NamedValue("Value", FormulaValue.New("Initial")));
this.State.Set("TestTable", FormulaValue.NewTable(recordType, initialRecord));

EditTableV2 firstAdd = this.CreateModel(
nameof(ConsecutiveAddItemOperationsPreserveTableAsync),
"TestTable",
this.CreateAddItemOperation(new StringDataValue("First")));
EditTableV2 secondAdd = this.CreateModel(
nameof(ConsecutiveAddItemOperationsPreserveTableAsync),
"TestTable",
this.CreateAddItemOperation(new StringDataValue("Second")));

// Act
await this.ExecuteAsync(new EditTableV2Executor(firstAdd, this.State));
await this.ExecuteAsync(new EditTableV2Executor(secondAdd, this.State));

// Assert
TableValue resultTable = Assert.IsAssignableFrom<TableValue>(this.State.Get("TestTable"));
string[] values = resultTable.Rows
.Select(row => Assert.IsType<StringValue>(row.Value.GetField("Value")).Value)
.ToArray();
Assert.Equal(["Initial", "First", "Second"], values);
}

[Fact]
public async Task ClearItemsOperationAsync()
{
Expand Down
Loading