Skip to content

Commit c0e71a3

Browse files
test: Added trigger by value container
1 parent b8d08f5 commit c0e71a3

7 files changed

Lines changed: 237 additions & 3 deletions

File tree

PowerAutomateMockUp/ExpressionParser/Functions/CustomException/InvalidTemplateException.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,5 +59,15 @@ public static InvalidTemplateException BuildInvalidTemplateExceptionParameterTyp
5959

6060
return new InvalidTemplateException(msg);
6161
}
62+
63+
public static InvalidTemplateException BuildInvalidLanguageFunction(string actionName, string functionName)
64+
{
65+
var msg = $"InvalidTemplate. Unable to process template language expressions in action '{actionName}' inputs at " +
66+
$"line 'x' and column 'y': 'The template language function '{functionName}' expects a comma separated " +
67+
"list of parameters. The function was invoked with no parameters. " +
68+
"Please see https://aka.ms/logicexpressions#createArray for usage details.'.";
69+
70+
return new InvalidTemplateException(msg);
71+
}
6272
}
6373
}

PowerAutomateMockUp/ExpressionParser/Rules/AccessValueRule.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public AccessValueRule(IRule func, IEnumerable<IRule> indexRules)
3030

3131
foreach (var accessor in indexes.Skip(1))
3232
{
33-
tempIndexRules.Add(new IndexRule(new ConstantRule(new ValueContainer(accessor)), false));
33+
tempIndexRules.Add(new IndexRule(new ConstantRule(new ValueContainer(accessor)), nullConditional));
3434
}
3535
}
3636
else

PowerAutomateMockUp/FlowParser/FlowRunner.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ public interface IFlowRunner
1616
{
1717
void InitializeFlowRunner(in string path);
1818
Task Trigger();
19+
Task Trigger(ValueContainer triggerOutput);
1920
}
2021

2122
public class FlowRunner : IFlowRunner
@@ -68,6 +69,13 @@ public async Task Trigger()
6869
await RunFlow();
6970
}
7071

72+
public async Task Trigger(ValueContainer triggerOutput)
73+
{
74+
_state.AddTriggerOutputs(triggerOutput);
75+
76+
await RunFlow();
77+
}
78+
7179
private async Task RunFlow()
7280
{
7381
var currentAd = _scopeManager.CurrentActionDescriptions.First(

PowerAutomateMockUp/FlowRunnerDependencyExtension.cs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
1-
using Microsoft.Extensions.DependencyInjection;
1+
using System;
2+
using Microsoft.Extensions.DependencyInjection;
23
using Parser.ExpressionParser;
34
using Parser.ExpressionParser.Functions.Base;
45
using Parser.ExpressionParser.Functions.Implementations.CollectionFunctions;
6+
using Parser.ExpressionParser.Functions.Implementations.ConversionFunctions;
57
using Parser.ExpressionParser.Functions.Implementations.LogicalComparisonFunctions;
68
using Parser.ExpressionParser.Functions.Implementations.StringFunctions;
79
using Parser.ExpressionParser.Functions.Storage;
810
using Parser.FlowParser;
911
using Parser.FlowParser.ActionExecutors;
1012
using Parser.FlowParser.ActionExecutors.Implementations;
13+
using Parser.FlowParser.ActionExecutors.Implementations.ControlActions;
1114
using LengthFunction = Parser.ExpressionParser.Functions.Implementations.StringFunctions.LengthFunction;
1215

1316
namespace Parser
@@ -31,6 +34,7 @@ public static void AddFlowRunner(this IServiceCollection services)
3134

3235
AddStringFunctions(services);
3336
AddCollectionFunction(services);
37+
AddConversionFunction(services);
3438

3539
services.AddTransient<IFunction, VariablesFunction>();
3640
services.AddTransient<IFunction, OutputsFunction>();
@@ -82,6 +86,19 @@ private static void AddCollectionFunction(IServiceCollection services)
8286
services.AddTransient<IFunction, UnionFunction>();
8387
}
8488

89+
private static void AddConversionFunction(IServiceCollection services)
90+
{
91+
services.AddTransient<IFunction, ArrayFunction>();
92+
services.AddTransient<IFunction, Base64Function>();
93+
services.AddTransient<IFunction, Base64ToBinaryFunction>();
94+
services.AddTransient<IFunction, Base64ToStringFunction>();
95+
services.AddTransient<IFunction, BinaryFunction>();
96+
services.AddTransient<IFunction, BoolFunction>();
97+
services.AddTransient<IFunction, CreateArrayFunction>();
98+
services.AddTransient<IFunction, DataUriFunction>();
99+
services.AddTransient<IFunction, DataUriToBinaryFunction>();
100+
}
101+
85102
public static void AddFlowActionByName<T>(this IServiceCollection services, string actionName)
86103
where T : ActionExecutorBase
87104
{
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
{
2+
"name": "24ed5667-14a8-4965-bc0c-d73ed8408aec",
3+
"id": "/providers/Microsoft.Flow/flows/24ed5667-14a8-4965-bc0c-d73ed8408aec",
4+
"type": "Microsoft.Flow/flows",
5+
"properties": {
6+
"apiId": "/providers/Microsoft.PowerApps/apis/shared_logicflows",
7+
"displayName": "Post 1 - Demonstration flow",
8+
"definition": {
9+
"$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
10+
"contentVersion": "1.0.0.0",
11+
"parameters": {
12+
"$connections": {
13+
"defaultValue": {},
14+
"type": "Object"
15+
},
16+
"$authentication": {
17+
"defaultValue": {},
18+
"type": "SecureObject"
19+
}
20+
},
21+
"triggers": {
22+
"When_a_Contact_is_created_or_updated": {
23+
"type": "OpenApiConnectionWebhook",
24+
"inputs": {
25+
"host": {
26+
"connectionName": "shared_commondataserviceforapps",
27+
"operationId": "SubscribeWebhookTrigger",
28+
"apiId": "/providers/Microsoft.PowerApps/apis/shared_commondataserviceforapps"
29+
},
30+
"parameters": {
31+
"subscriptionRequest/message": 4,
32+
"subscriptionRequest/entityname": "contact",
33+
"subscriptionRequest/scope": 4
34+
},
35+
"authentication": "@parameters('$authentication')"
36+
}
37+
}
38+
},
39+
"actions": {
40+
"Condition_-_If_the_last_name_is_empty": {
41+
"actions": {
42+
"Send_me_an_email_notification": {
43+
"runAfter": {},
44+
"type": "OpenApiConnection",
45+
"inputs": {
46+
"host": {
47+
"connectionName": "shared_flowpush",
48+
"operationId": "SendEmailNotification",
49+
"apiId": "/providers/Microsoft.PowerApps/apis/shared_flowpush"
50+
},
51+
"parameters": {
52+
"NotificationEmailDefinition/notificationSubject": "WARNING: Newly created contact does not have a last name",
53+
"NotificationEmailDefinition/notificationBody": "Contact with id @{triggerOutputs()?['body/contactid']} does not have a last name."
54+
},
55+
"authentication": "@parameters('$authentication')"
56+
}
57+
}
58+
},
59+
"runAfter": {},
60+
"else": {
61+
"actions": {
62+
"Create_a_new_row_-_Create_greeting_note": {
63+
"runAfter": {},
64+
"type": "OpenApiConnection",
65+
"inputs": {
66+
"host": {
67+
"connectionName": "shared_commondataserviceforapps",
68+
"operationId": "CreateRecord",
69+
"apiId": "/providers/Microsoft.PowerApps/apis/shared_commondataserviceforapps"
70+
},
71+
"parameters": {
72+
"entityName": "annotations",
73+
"item/subject": "Greet our new Contact ",
74+
"item/notetext": "With the name of @{triggerOutputs()?['body/fullname']}",
75+
"item/isdocument": false
76+
},
77+
"authentication": "@parameters('$authentication')"
78+
}
79+
}
80+
}
81+
},
82+
"expression": {
83+
"equals": [
84+
"@empty(triggerOutputs()?['body/lastname'])",
85+
"@true"
86+
]
87+
},
88+
"type": "If"
89+
}
90+
},
91+
"outputs": {}
92+
},
93+
"connectionReferences": {
94+
"shared_flowpush": {
95+
"source": "Embedded",
96+
"id": "/providers/Microsoft.PowerApps/apis/shared_flowpush",
97+
"tier": "NotSpecified"
98+
},
99+
"shared_commondataserviceforapps": {
100+
"source": "Embedded",
101+
"id": "/providers/Microsoft.PowerApps/apis/shared_commondataserviceforapps",
102+
"tier": "NotSpecified"
103+
}
104+
},
105+
"flowFailureAlertSubscribed": false
106+
}
107+
}

Test/FullFlowTest.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
using NUnit.Framework;
66
using Parser;
77
using Parser.ExpressionParser;
8-
using Parser.ExpressionParser.Functions.Base;
98
using Parser.FlowParser;
109
using Parser.FlowParser.ActionExecutors;
1110

Test/TestValueContainerTrigger.cs

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
using System.Collections.Generic;
2+
using System.Threading.Tasks;
3+
using Microsoft.Extensions.DependencyInjection;
4+
using NUnit.Framework;
5+
using Parser;
6+
using Parser.ExpressionParser;
7+
using Parser.FlowParser;
8+
using Parser.FlowParser.ActionExecutors;
9+
10+
namespace Test
11+
{
12+
[TestFixture]
13+
public class TestValueContainerTrigger
14+
{
15+
private static readonly string TestFlowPath = System.IO.Path.GetFullPath(@"FlowSamples");
16+
17+
[Test]
18+
public async Task TestFlowFalse()
19+
{
20+
// Arrange
21+
var path = @$"{TestFlowPath}\ContactTrigger.json";
22+
23+
var services = new ServiceCollection();
24+
25+
services.AddFlowActionByName<UpdateRowActionExecutor>(UpdateRowActionExecutor.FlowActionName);
26+
services.AddFlowActionByName<SendNotification>(SendNotification.FlowActionName);
27+
28+
services.AddFlowRunner();
29+
30+
var sp = services.BuildServiceProvider();
31+
var flowRunner = sp.GetRequiredService<IFlowRunner>();
32+
33+
flowRunner.InitializeFlowRunner(path);
34+
35+
var triggerOutput = new ValueContainer(new Dictionary<string, ValueContainer>
36+
{
37+
{
38+
"body", new ValueContainer(new Dictionary<string, ValueContainer>
39+
{
40+
{"firstname", new ValueContainer("John")},
41+
// {"lastname", new ValueContainer("Doe")}
42+
})
43+
}
44+
});
45+
46+
// Act
47+
await flowRunner.Trigger(triggerOutput);
48+
49+
// Assert
50+
var state = sp.GetRequiredService<IState>();
51+
52+
Assert.IsTrue(state.GetOutputs(SendNotification.FlowActionName).Type() != ValueContainer.ValueType.Null);
53+
Assert.IsTrue(state.GetOutputs(UpdateRowActionExecutor.FlowActionName).Type() == ValueContainer.ValueType.Null);
54+
55+
Assert.IsTrue(state.GetOutputs(SendNotification.FlowActionName).GetValue<bool>(),
56+
"Second action wasn't triggered");
57+
}
58+
}
59+
60+
public class UpdateRowActionExecutor : OpenApiConnectionActionExecutorBase
61+
{
62+
public static string FlowActionName = "Create_a_new_row_-_Create_greeting_note";
63+
64+
public UpdateRowActionExecutor(IExpressionEngine expressionEngine) : base(expressionEngine)
65+
{
66+
}
67+
68+
public override Task<ActionResult> Execute()
69+
{
70+
return Task.FromResult(new ActionResult
71+
{
72+
ActionOutput = new ValueContainer(true)
73+
});
74+
}
75+
}
76+
77+
public class SendNotification : OpenApiConnectionActionExecutorBase
78+
{
79+
public static string FlowActionName = "Send_me_an_email_notification";
80+
81+
public SendNotification(IExpressionEngine expressionEngine) : base(expressionEngine)
82+
{
83+
}
84+
85+
public override Task<ActionResult> Execute()
86+
{
87+
return Task.FromResult(new ActionResult
88+
{
89+
ActionOutput = new ValueContainer(true)
90+
});
91+
}
92+
}
93+
}

0 commit comments

Comments
 (0)