Skip to content

Commit c2d0479

Browse files
Merge pull request #16 from thygesteffensen/fix/tryparseparameters
Fix/tryparseparameters
2 parents cfcc84c + c1afee5 commit c2d0479

File tree

10 files changed

+153
-40
lines changed

10 files changed

+153
-40
lines changed

.github/workflows/todo.yml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
name: "Create issues from todo"
2+
3+
on:
4+
push:
5+
branches:
6+
- dev
7+
8+
jobs:
9+
build:
10+
runs-on: "ubuntu-latest"
11+
steps:
12+
- uses: "actions/checkout@master"
13+
- name: "TODO to Issue"
14+
uses: "alstr/todo-to-issue-action@v2.4"
15+
id: "todo"
16+
with:
17+
TOKEN: ${{ secrets.GITHUB_TOKEN }}
18+
COMMENT_MARKER: "//"
19+
LABEL: "// TODO"

PowerAutomateMockUp/ExpressionParser/ValueContainer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ public ValueContainer this[string key]
205205
}
206206
}
207207

208-
private Dictionary<string, ValueContainer> AsDict()
208+
public Dictionary<string, ValueContainer> AsDict()
209209
{
210210
if (_type == ValueType.Object)
211211
{

PowerAutomateMockUp/FlowParser/ActionExecutors/Implementations/ScopeActionExecutor.cs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,19 @@ public ScopeActionExecutor(ScopeDepthManager scopeDepthManager)
1616

1717
public override Task<ActionResult> Execute()
1818
{
19-
var scopeActionJson = Json.Parent;
20-
var scopeName = ((JProperty) scopeActionJson).Name;
21-
2219
var scopeActionDescriptions = Json.SelectToken("$.actions").OfType<JProperty>();
2320
var actionDescriptions = scopeActionDescriptions as JProperty[] ?? scopeActionDescriptions.ToArray();
24-
25-
_scopeDepthManager.Push(scopeName, actionDescriptions);
21+
22+
_scopeDepthManager.Push(ActionName, actionDescriptions, null);
2623

2724
var firstScopeAction = actionDescriptions.First(ad => !ad.Value.SelectToken("$.runAfter").Any());
2825

2926
return Task.FromResult(new ActionResult {NextAction = firstScopeAction.Name});
3027
}
3128
}
29+
30+
public interface IScopeActionExecutor
31+
{
32+
public Task<ActionResult> ExitScope(ActionStatus scopeStatus);
33+
}
3234
}

PowerAutomateMockUp/FlowParser/ActionExecutors/OpenApiConnectionBaseActionExecutor.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ protected override void ProcessJson()
3131
foreach (var keyValuePar in content.Parameters)
3232
{
3333
// TODO: Here is an use case where the engine could have just returned a Value Container instead!
34-
Parameters[keyValuePar.Key] = new ValueContainer(_expressionEngine.Parse(keyValuePar.Value));
34+
Parameters[keyValuePar.Key] = new ValueContainer(_expressionEngine.Parse(keyValuePar.Value), true);
3535
}
3636
}
3737

PowerAutomateMockUp/FlowParser/FlowRunner.cs

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public void InitializeFlowRunner(in string path)
4040
var flowJson = JToken.ReadFrom(jsonTextReader);
4141
var flowDefinition = flowJson.SelectToken("$.*.definition");
4242
_trigger = flowDefinition.SelectToken("$.triggers").First as JProperty;
43-
_scopeManager.Push("root", flowDefinition.SelectToken("$.actions").OfType<JProperty>());
43+
_scopeManager.Push("root", flowDefinition.SelectToken("$.actions").OfType<JProperty>(), null);
4444
}
4545

4646
public async Task<object> Trigger(ValueContainer triggerOutputs)
@@ -56,7 +56,7 @@ public async Task Trigger()
5656
{
5757
var trigger = GetActionExecutor(_trigger);
5858

59-
trigger.InitializeActionExecutor(_trigger.Name ,_trigger.Value);
59+
trigger.InitializeActionExecutor(_trigger.Name, _trigger.Value);
6060
await trigger.Execute();
6161

6262
await RunFlow();
@@ -72,9 +72,8 @@ private async Task RunFlow()
7272
if (_flowRunnerSettings.IgnoreActions.Contains(currentAd.Name))
7373
{
7474
currentAd = _scopeManager.CurrentActionDescriptions.FirstOrDefault(a =>
75-
a.Value.SelectToken("$.runAfter").First?.ToObject<JProperty>().Name ==
76-
currentAd.Name &&
77-
a.Value.SelectToken("$.runAfter.*").Values().Any(
75+
a.Value.SelectToken("$.runAfter").First?.ToObject<JProperty>().Name == currentAd.Name
76+
&& a.Value.SelectToken("$.runAfter.*").Values().Any(
7877
x => x?.Value<string>() == ActionStatus.Succeeded.ToString()));
7978
continue;
8079
}
@@ -87,30 +86,43 @@ private async Task RunFlow()
8786
break;
8887
}
8988

89+
// If an action failes inside a scope, and a suitable action isn't found inside the given scope, that
90+
// actions status is transferred to be the scope status. This isn't the case atm
91+
92+
// TODO: Figure out how to get actionResult from
9093
var actionDescName = currentAd.Name;
91-
while (!DetermineNextAction(actionResult, out currentAd, actionDescName))
94+
var nextAction = actionResult.NextAction;
95+
var actionResultStatus = actionResult.ActionStatus;
96+
while (!DetermineNextAction(nextAction, actionResultStatus, out currentAd, actionDescName))
9297
{
93-
if (!_scopeManager.TryPopScope(out actionDescName))
98+
nextAction = null;
99+
var t = await _scopeManager.TryPopScope(actionResultStatus);
100+
if (t == null)
94101
{
102+
currentAd = null;
95103
break;
96104
}
105+
106+
actionResultStatus = t.ActionStatus;
107+
actionDescName = t.NextAction;
97108
}
98109
}
99110
}
100111

101-
private bool DetermineNextAction(ActionResult actionResult, out JProperty currentActionDesc, string adName)
112+
private bool DetermineNextAction(string nextAction, ActionStatus actionResultStatus,
113+
out JProperty currentActionDesc, string adName)
102114
{
103-
if (actionResult?.NextAction == null)
115+
if (nextAction == null)
104116
{
105117
currentActionDesc = _scopeManager.CurrentActionDescriptions.FirstOrDefault(a =>
106118
a.Value.SelectToken("$.runAfter").First?.ToObject<JProperty>().Name == adName &&
107119
a.Value.SelectToken("$.runAfter.*").Values().Any(
108-
x => x?.Value<string>() == actionResult?.ActionStatus.ToString()));
120+
x => x?.Value<string>() == actionResultStatus.ToString()));
109121
}
110122
else
111123
{
112124
currentActionDesc =
113-
_scopeManager.CurrentActionDescriptions.First(a => a.Name == actionResult.NextAction);
125+
_scopeManager.CurrentActionDescriptions.First(a => a.Name == nextAction);
114126
}
115127

116128
return currentActionDesc != null;
@@ -121,7 +133,7 @@ private static async Task<ActionResult> ExecuteAction(ActionExecutorBase actionE
121133
{
122134
if (actionExecutor == null) return null;
123135

124-
actionExecutor.InitializeActionExecutor(currentAction.Name ,currentAction.First);
136+
actionExecutor.InitializeActionExecutor(currentAction.Name, currentAction.First);
125137
return await actionExecutor.Execute();
126138
}
127139

PowerAutomateMockUp/PowerAutomateMockUp.csproj

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@
1919
<ItemGroup>
2020
<!--<FrameworkReference Include="Microsoft.AspNetCore.App" />-->
2121
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
22-
<PackageReference Include="Microsoft.Extensions.Configuration" Version="3.1.9" />
23-
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.1.9" />
24-
<PackageReference Include="Microsoft.Extensions.Options" Version="3.1.9" />
25-
<PackageReference Include="Microsoft.Extensions.Logging" Version="3.1.9" />
26-
<PackageReference Include="Newtonsoft.Json" Version="9.0.1" />
22+
<PackageReference Include="Microsoft.Extensions.Configuration" Version="5.0.0" />
23+
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="5.0.1" />
24+
<PackageReference Include="Microsoft.Extensions.Options" Version="5.0.0" />
25+
<PackageReference Include="Microsoft.Extensions.Logging" Version="5.0.0" />
26+
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
2727
<PackageReference Include="Sprache" Version="2.3.1" />
2828
</ItemGroup>
2929

PowerAutomateMockUp/ScopeDepthManager.cs

Lines changed: 48 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,38 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Linq;
4+
using System.Threading.Tasks;
5+
using Microsoft.Extensions.Logging;
46
using Newtonsoft.Json.Linq;
5-
using Parser.ExpressionParser.Functions.CustomException;
7+
using Parser.FlowParser.ActionExecutors;
8+
using Parser.FlowParser.ActionExecutors.Implementations;
69

710
namespace Parser
811
{
912
public class ScopeDepthManager
1013
{
14+
private readonly ILogger<ScopeDepthManager> _logger;
1115
public IEnumerable<JProperty> CurrentActionDescriptions { get; private set; }
1216

1317
private readonly Stack<string> _scopes;
18+
private readonly Stack<IScopeActionExecutor> _scopeActionExecutors;
1419
private readonly Stack<IEnumerable<JProperty>> _actionDescriptions;
1520

16-
public ScopeDepthManager()
21+
public ScopeDepthManager(ILogger<ScopeDepthManager> logger)
1722
{
23+
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
1824
_actionDescriptions = new Stack<IEnumerable<JProperty>>();
1925
_scopes = new Stack<string>();
26+
_scopeActionExecutors = new Stack<IScopeActionExecutor>();
2027
}
2128

22-
public void Push(string scopeName, IEnumerable<JProperty> scopeActionDescriptions)
29+
public void Push(
30+
string scopeName,
31+
IEnumerable<JProperty> scopeActionDescriptions,
32+
IScopeActionExecutor scopeActionExecutor)
2333
{
34+
_logger.LogInformation("Entered a scope ({scopeName}).", scopeName);
35+
2436
var scopeActionDescriptionsAsList =
2537
scopeActionDescriptions as JProperty[] ?? scopeActionDescriptions.ToArray();
2638

@@ -34,14 +46,20 @@ public void Push(string scopeName, IEnumerable<JProperty> scopeActionDescription
3446
CurrentActionDescriptions = scopeActionDescriptionsAsList;
3547

3648
_scopes.Push(scopeName);
49+
50+
_scopeActionExecutors.Push(scopeActionExecutor);
3751
}
3852
}
3953

40-
public bool TryPopScope(out string scopeName)
54+
public async Task<ActionResult> TryPopScope(ActionStatus scopeStatus)
4155
{
56+
_logger.LogInformation("Exiting scope.");
57+
4258
#if DOT_NET_CORE
43-
var scopePopSuccessful = _scopes.TryPop(out scopeName);
59+
var scopePopSuccessful = _scopes.TryPop(out var scopeName);
4460
#else
61+
string scopeName;
62+
4563
var scopePopSuccessful = true;
4664
try
4765
{
@@ -54,12 +72,34 @@ public bool TryPopScope(out string scopeName)
5472
}
5573
#endif
5674

57-
if (scopePopSuccessful)
75+
// Todo: Finish the State Machine and figure out how this should be handled properly
76+
77+
78+
if (!scopePopSuccessful)
79+
{
80+
return null;
81+
}
82+
83+
CurrentActionDescriptions = _actionDescriptions.Pop();
84+
85+
var t = _scopeActionExecutors.Pop();
86+
87+
ActionResult exitScopeResult = null;
88+
if (t == null)
89+
{
90+
_logger.LogInformation("Scope action does not have a exit scope action.");
91+
}
92+
else
5893
{
59-
CurrentActionDescriptions = _actionDescriptions.Pop();
94+
exitScopeResult = await t.ExitScope(scopeStatus);
6095
}
6196

62-
return scopePopSuccessful;
97+
98+
return await Task.FromResult(new ActionResult
99+
{
100+
ActionStatus = exitScopeResult?.ActionStatus ?? scopeStatus,
101+
NextAction = scopeName
102+
});
63103
}
64104
}
65105
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
using System.Collections.Generic;
2+
using System.Threading.Tasks;
3+
using Moq;
4+
using Newtonsoft.Json.Linq;
5+
using NUnit.Framework;
6+
using Parser;
7+
using Parser.FlowParser.ActionExecutors;
8+
using Parser.FlowParser.ActionExecutors.Implementations;
9+
10+
namespace Test.ActionTests
11+
{
12+
[TestFixture]
13+
public class ScopeActionExecutorTest
14+
{
15+
[Test]
16+
public async Task TestBasicScopeUseCase()
17+
{
18+
var logger = TestLogger.Create<ScopeDepthManager>();
19+
20+
var scopeDepthManager = new ScopeDepthManager(logger);
21+
scopeDepthManager.Push("rootScope", new List<JProperty>(), null);
22+
23+
var t = new Mock<IScopeActionExecutor>();
24+
t.Setup(x => x.ExitScope(ActionStatus.Succeeded)).Returns(Task.FromResult(new ActionResult()));
25+
26+
scopeDepthManager.Push("testScope", new List<JProperty>(), t.Object);
27+
28+
var t1 = await scopeDepthManager.TryPopScope(ActionStatus.Succeeded);
29+
30+
t.Verify(x => x.ExitScope(ActionStatus.Succeeded));
31+
32+
Assert.AreEqual(t1.ActionStatus, ActionStatus.Succeeded);
33+
Assert.AreEqual(t1.NextAction, "testScope");
34+
Assert.AreEqual(t1.ContinueExecution, true);
35+
}
36+
}
37+
}

Test/ParserTest.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,17 +136,17 @@ public void TestTriggerOutputs(TestInput testInput)
136136

137137
private static object[] _triggerOutputTest =
138138
{
139-
new TestInput("@triggerOutputs()['body/dca_entrytype']", "OCR payment")
139+
new TestInput("@triggerOutputs()['body/entrytype']", "OCR payment")
140140
{
141141
ValueContainers = new[]
142142
{
143143
new ValueContainer(new Dictionary<string, ValueContainer>
144144
{
145-
{"body/dca_entrytype", new ValueContainer("OCR payment")}
145+
{"body/entrytype", new ValueContainer("OCR payment")}
146146
})
147147
}
148148
},
149-
/*new TestInput("@triggerOutputs()?['body/dca_entrytype']", null)
149+
/*new TestInput("@triggerOutputs()?['body/entrytype']", null)
150150
{
151151
ValueContainers = new[]
152152
{

Test/Test.csproj

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,15 @@
1313

1414
<ItemGroup>
1515
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
16-
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.1.9" />
17-
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" />
16+
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="5.0.1" />
17+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.3" />
1818
<PackageReference Include="Moq" Version="4.15.2" />
19-
<PackageReference Include="MSTest.TestAdapter" Version="2.1.0" />
20-
<PackageReference Include="MSTest.TestFramework" Version="2.1.0" />
21-
<PackageReference Include="coverlet.collector" Version="1.2.0" />
19+
<PackageReference Include="MSTest.TestAdapter" Version="2.1.2" />
20+
<PackageReference Include="MSTest.TestFramework" Version="2.1.2" />
21+
<PackageReference Include="coverlet.collector" Version="1.3.0">
22+
<PrivateAssets>all</PrivateAssets>
23+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
24+
</PackageReference>
2225
<PackageReference Include="NUnit" Version="3.12.0" />
2326
<PackageReference Include="NUnit3TestAdapter" Version="3.17.0" />
2427
</ItemGroup>

0 commit comments

Comments
 (0)