Skip to content

Commit 664b22b

Browse files
Copilotcrickman
andauthored
.NET Workflows - Add unit tests for QuestionExecutor (#3892)
* Initial plan * Add comprehensive unit tests for QuestionExecutor Co-authored-by: crickman <66376200+crickman@users.noreply.github.com> * Address code review feedback and add additional test for default value logic Co-authored-by: crickman <66376200+crickman@users.noreply.github.com> * Checkpoint * Polished --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: crickman <66376200+crickman@users.noreply.github.com> Co-authored-by: Chris Rickman <crickman@microsoft.com>
1 parent dcc106e commit 664b22b

2 files changed

Lines changed: 516 additions & 11 deletions

File tree

dotnet/src/Microsoft.Agents.AI.Workflows.Declarative/ObjectModel/QuestionExecutor.cs

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -44,18 +44,17 @@ public static bool IsComplete(object? message)
4444
await this._promptCount.WriteAsync(context, 0).ConfigureAwait(false);
4545

4646
InitializablePropertyPath variable = Throw.IfNull(this.Model.Variable);
47-
bool hasValue = context.ReadState(variable.Path) is BlankValue;
48-
bool alwaysPrompt = this.Evaluator.GetValue(this.Model.AlwaysPrompt).Value;
47+
bool isValueUndefined = context.ReadState(variable.Path) is BlankValue;
48+
bool proceed = this.Evaluator.GetValue(this.Model.AlwaysPrompt).Value;
4949

50-
bool proceed = !alwaysPrompt || hasValue;
51-
if (proceed)
50+
if (!proceed)
5251
{
5352
SkipQuestionMode mode = this.Evaluator.GetValue(this.Model.SkipQuestionMode).Value;
5453
proceed =
5554
mode switch
5655
{
57-
SkipQuestionMode.SkipOnFirstExecutionIfVariableHasValue => !await this._hasExecuted.ReadAsync(context).ConfigureAwait(false),
58-
SkipQuestionMode.AlwaysSkipIfVariableHasValue => hasValue,
56+
SkipQuestionMode.SkipOnFirstExecutionIfVariableHasValue => isValueUndefined && !await this._hasExecuted.ReadAsync(context).ConfigureAwait(false),
57+
SkipQuestionMode.AlwaysSkipIfVariableHasValue => isValueUndefined,
5958
SkipQuestionMode.AlwaysAsk => true,
6059
_ => true,
6160
};
@@ -86,7 +85,7 @@ public async ValueTask CaptureResponseAsync(IWorkflowContext context, ExternalIn
8685
FormulaValue? extractedValue = null;
8786
if (!response.HasMessages)
8887
{
89-
string unrecognizedResponse = this.FormatPrompt(this.Model.UnrecognizedPrompt);
88+
string unrecognizedResponse = this.Model.UnrecognizedPrompt is not null ? this.FormatPrompt(this.Model.UnrecognizedPrompt) : "Invalid response";
9089
await context.AddEventAsync(new MessageActivityEvent(unrecognizedResponse.Trim()), cancellationToken).ConfigureAwait(false);
9190
}
9291
else
@@ -128,7 +127,7 @@ public async ValueTask CaptureResponseAsync(IWorkflowContext context, ExternalIn
128127
}
129128
}
130129

131-
await this.AssignAsync(this.Model.Variable?.Path, extractedValue, context).ConfigureAwait(false);
130+
await this.AssignAsync(Throw.IfNull(this.Model.Variable).Path, extractedValue, context).ConfigureAwait(false);
132131
await this._hasExecuted.WriteAsync(context, true).ConfigureAwait(false);
133132
await context.SendResultMessageAsync(this.Id, cancellationToken).ConfigureAwait(false);
134133
}
@@ -145,9 +144,13 @@ private async ValueTask PromptAsync(IWorkflowContext context, CancellationToken
145144
int actualCount = await this._promptCount.ReadAsync(context).ConfigureAwait(false);
146145
if (actualCount >= repeatCount)
147146
{
148-
ValueExpression defaultValueExpression = Throw.IfNull(this.Model.DefaultValue);
149-
DataValue defaultValue = this.Evaluator.GetValue(defaultValueExpression).Value;
150-
await this.AssignAsync(this.Model.Variable?.Path, defaultValue.ToFormula(), context).ConfigureAwait(false);
147+
DataValue defaultValue = DataValue.Blank();
148+
if (this.Model.DefaultValue is not null)
149+
{
150+
ValueExpression defaultValueExpression = Throw.IfNull(this.Model.DefaultValue);
151+
defaultValue = this.Evaluator.GetValue(defaultValueExpression).Value;
152+
}
153+
await this.AssignAsync(Throw.IfNull(this.Model.Variable).Path, defaultValue.ToFormula(), context).ConfigureAwait(false);
151154
string defaultValueResponse = this.FormatPrompt(this.Model.DefaultValueResponse);
152155
await context.AddEventAsync(new MessageActivityEvent(defaultValueResponse.Trim()), cancellationToken).ConfigureAwait(false);
153156
await context.SendResultMessageAsync(this.Id, cancellationToken).ConfigureAwait(false);

0 commit comments

Comments
 (0)