From 0f7a61cec75c8505fa9a31df449bf433af004e4e Mon Sep 17 00:00:00 2001 From: Thyge Skoedt Steffensen <31892312+thygesteffensen@users.noreply.github.com> Date: Tue, 20 Jul 2021 17:23:31 +0200 Subject: [PATCH 1/3] fix: Bug where indexing didn't work with expressions in strings E.g. "Hello @{variables('account').name} and welcome", would produce "Hello John Doe and welcome", but instead just be an empty string. Furthermore, charPreFixedString, i.e. strings starting with an '@' is no longer a feature/bug in PowerAutomate. --- ExpressionEngine/ExpressionGrammar.cs | 16 ++-------------- Test/ParserTest.cs | 4 +--- 2 files changed, 3 insertions(+), 17 deletions(-) diff --git a/ExpressionEngine/ExpressionGrammar.cs b/ExpressionEngine/ExpressionGrammar.cs index a70329b..00d97a1 100644 --- a/ExpressionEngine/ExpressionGrammar.cs +++ b/ExpressionEngine/ExpressionGrammar.cs @@ -66,14 +66,7 @@ from index in _method.Or(stringLiteral).Or(integer).Contained(lBracket, rBracket from nll in nullConditional from dot in Parse.Char('.') from index in Parse.AnyChar.Except( - lBracket - .Or(rBracket) - .Or(lParenthesis) - .Or(rParenthesis) - .Or(Parse.Char('@')) - .Or(Parse.Char(',')) - .Or(Parse.Char('.')) - .Or(Parse.Char('?')) + Parse.Chars('[', ']', '{', '}', '[', ']', '@', ',', '.', '?') ).Many().Text() select new IndexRule(new StringLiteralRule(new ValueContainer(index)), nll); @@ -123,12 +116,7 @@ from exp in enclosedExpression.Optional() .Many() select new ValueTask(new ValueContainer(string.Concat(e))); - Parser> charPrefixedString = - from at in Parse.Char('@') - from str in Parse.LetterOrDigit.Many().Text().Except(Parse.Chars('{', '@')) - select new ValueTask(new ValueContainer(str)); - - _input = expression.Or(charPrefixedString).Or(joinedString); + _input = expression.Or(joinedString); } public async ValueTask EvaluateToString(string input) diff --git a/Test/ParserTest.cs b/Test/ParserTest.cs index 078245e..385894b 100644 --- a/Test/ParserTest.cs +++ b/Test/ParserTest.cs @@ -88,9 +88,7 @@ public async Task TestSimpleInput(TestInput testInput) new TestInput("Hej med dig @{toUpper(\'charlie\')}", new ValueContainer("Hej med dig CHARLIE")), new TestInput("@{toLower(\'Hej med dig \')}@{trim(\' Mads \')}", new ValueContainer("hej med dig Mads")), new TestInput("@@1", new ValueContainer("@1")), - new TestInput("@aes", new ValueContainer("aes")), - new TestInput("@empty(trim(' ')?.name1)", new ValueContainer(true)), - new TestInput("@not(empty(trim(' ')?.name1))", new ValueContainer(false)) + new TestInput("aes", new ValueContainer("aes")), }; #endregion From 2f0bd85c4946094a862258982b4da972884e25ce Mon Sep 17 00:00:00 2001 From: Thyge Skoedt Steffensen <31892312+thygesteffensen@users.noreply.github.com> Date: Tue, 20 Jul 2021 17:26:15 +0200 Subject: [PATCH 2/3] fix: Added exception in AccessValueRule.cs to throw when the ValueContainer is neither an object or list. PowerAutomate only allow objects and lists being indexed and PowerAutomate throws an error when this is done on other types, this have been added to the AccessValueRule.cs and it throws an error similar to PowerAutomate. --- ExpressionEngine/Rules/AccessValueRule.cs | 6 +++++- Test/ExpressionGrammarTest.cs | 18 +++++++++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/ExpressionEngine/Rules/AccessValueRule.cs b/ExpressionEngine/Rules/AccessValueRule.cs index 877c29d..687a20e 100644 --- a/ExpressionEngine/Rules/AccessValueRule.cs +++ b/ExpressionEngine/Rules/AccessValueRule.cs @@ -70,7 +70,11 @@ public async ValueTask Evaluate() } } - return currentValue; + throw new InvalidTemplateException( + "Unable to process template language expressions in action 'Compose' inputs " + + $"at line 'x' and column 'y': 'The template language expression '{_func.PrettyPrint()}{(nullConditional ? "?" : "")}.{index}' cannot be " + + $"evaluated because property '{index}' cannot be selected. Property selection is not supported on values " + + $"of type '{currentValue.Type()}'."); } public string PrettyPrint() diff --git a/Test/ExpressionGrammarTest.cs b/Test/ExpressionGrammarTest.cs index 2c02785..5ae1351 100644 --- a/Test/ExpressionGrammarTest.cs +++ b/Test/ExpressionGrammarTest.cs @@ -2,6 +2,7 @@ using System.Threading.Tasks; using ExpressionEngine; using ExpressionEngine.Functions.Base; +using ExpressionEngine.Functions.CustomException; using NUnit.Framework; namespace Test @@ -68,7 +69,7 @@ public async Task BooleanTest() [Test] public async Task NullConditional() { - _dummyFunction.ValueContainer = new ValueContainer(); + _dummyFunction.ValueContainer = new ValueContainer(new Dictionary()); const string expressionString = "@dummyFunction()?.name1"; @@ -77,6 +78,21 @@ public async Task NullConditional() Assert.NotNull(result); Assert.AreEqual(ValueContainer.ValueType.Null, result.Type()); } + + [Test] + public async Task IndexOnNonObject() + { + _dummyFunction.ValueContainer = new ValueContainer(""); + + const string expressionString = "@dummyFunction()?.name1"; + + var exception = Assert.ThrowsAsync(async () => await _expressionGrammar.EvaluateToValueContainer(expressionString)); + + Assert.AreEqual("Unable to process template language expressions in action 'Compose' inputs " + + "at line 'x' and column 'y': 'The template language expression 'dummyFunction()?.name1' cannot be " + + "evaluated because property 'name1' cannot be selected. Property selection is not supported on values " + + "of type 'String'.", exception.Message); + } } public class DummyFunction : Function From a51a544a7b71d5c133b12a7a4dde8136387e7ce6 Mon Sep 17 00:00:00 2001 From: Thyge Skoedt Steffensen <31892312+thygesteffensen@users.noreply.github.com> Date: Tue, 20 Jul 2021 17:27:17 +0200 Subject: [PATCH 3/3] refactor: Renamed PowerAutomateMockUpException.cs to ExpressionEngineException.cs to avoid confusion and removed the NotYetImplementedException. --- ExpressionEngine/ExpressionEngineException.cs | 11 ++++ .../CollectionFunctions/ContainsFunction.cs | 2 +- .../CollectionFunctions/EmptyFunction.cs | 2 +- .../CollectionFunctions/FirstFunction.cs | 2 +- .../IntersectionFunction.cs | 2 +- .../CollectionFunctions/LastFunction.cs | 2 +- .../CollectionFunctions/SkipFunction.cs | 2 +- .../CollectionFunctions/TakeFunction.cs | 2 +- .../CollectionFunctions/UnionFunction.cs | 2 +- .../ConversionFunctions/ArrayFunction.cs | 2 +- .../ConversionFunctions/Base64Function.cs | 2 +- .../Base64ToBinaryFunction.cs | 2 +- .../Base64ToStringFunction.cs | 2 +- .../ConversionFunctions/BinaryFunction.cs | 2 +- .../ConversionFunctions/BoolFunction.cs | 4 +- .../ConversionFunctions/DataUriFunction.cs | 2 +- .../DataUriToBinaryFunction.cs | 2 +- .../StringFunctions/AuxiliaryMethods.cs | 2 +- .../StringFunctions/FormatNumberFunction.cs | 2 +- .../StringFunctions/GuidFunction.cs | 2 +- .../StringFunctions/SubstringFunction.cs | 2 +- .../PowerAutomateMockUpException.cs | 12 ----- ExpressionEngine/ValueContainer.cs | 12 ++--- Test/IndexTest.cs | 52 ++++++++++++++++++- 24 files changed, 88 insertions(+), 41 deletions(-) create mode 100644 ExpressionEngine/ExpressionEngineException.cs delete mode 100644 ExpressionEngine/PowerAutomateMockUpException.cs diff --git a/ExpressionEngine/ExpressionEngineException.cs b/ExpressionEngine/ExpressionEngineException.cs new file mode 100644 index 0000000..de38c3a --- /dev/null +++ b/ExpressionEngine/ExpressionEngineException.cs @@ -0,0 +1,11 @@ +using System; + +namespace ExpressionEngine +{ + internal class ExpressionEngineException : Exception + { + public ExpressionEngineException(string message) : base(message) + { + } + } +} \ No newline at end of file diff --git a/ExpressionEngine/Functions/Implementations/CollectionFunctions/ContainsFunction.cs b/ExpressionEngine/Functions/Implementations/CollectionFunctions/ContainsFunction.cs index f9f417f..6003f96 100644 --- a/ExpressionEngine/Functions/Implementations/CollectionFunctions/ContainsFunction.cs +++ b/ExpressionEngine/Functions/Implementations/CollectionFunctions/ContainsFunction.cs @@ -44,7 +44,7 @@ public override ValueTask ExecuteFunction(params ValueContainer[ var substring = value.GetValue(); return new ValueTask(new ValueContainer(text.Contains(substring))); default: - throw new PowerAutomateMockUpException($"Cannot perform contains on {collection.Type()}."); + throw new ExpressionEngineException($"Cannot perform contains on {collection.Type()}."); } } } diff --git a/ExpressionEngine/Functions/Implementations/CollectionFunctions/EmptyFunction.cs b/ExpressionEngine/Functions/Implementations/CollectionFunctions/EmptyFunction.cs index 8ccc8be..f99d3dd 100644 --- a/ExpressionEngine/Functions/Implementations/CollectionFunctions/EmptyFunction.cs +++ b/ExpressionEngine/Functions/Implementations/CollectionFunctions/EmptyFunction.cs @@ -24,7 +24,7 @@ public override ValueTask ExecuteFunction(params ValueContainer[ ValueContainer.ValueType.Object => new ValueTask(new ValueContainer( value.GetValue>().Count == 0)), ValueContainer.ValueType.Null => new ValueTask(new ValueContainer(true)), - _ => throw new PowerAutomateMockUpException( + _ => throw new ExpressionEngineException( $"Empty expression can only operate on String, Array or Object types, not {value.Type()}.") }; } diff --git a/ExpressionEngine/Functions/Implementations/CollectionFunctions/FirstFunction.cs b/ExpressionEngine/Functions/Implementations/CollectionFunctions/FirstFunction.cs index 768bb9e..df046d2 100644 --- a/ExpressionEngine/Functions/Implementations/CollectionFunctions/FirstFunction.cs +++ b/ExpressionEngine/Functions/Implementations/CollectionFunctions/FirstFunction.cs @@ -21,7 +21,7 @@ public override ValueTask ExecuteFunction(params ValueContainer[ value.GetValue().Substring(0, 1))), ValueContainer.ValueType.Array => new ValueTask(new ValueContainer( value.GetValue>().First())), - _ => throw new PowerAutomateMockUpException( + _ => throw new ExpressionEngineException( $"Empty expression can only operate on String or Array types, not {value.Type()}.") }; } diff --git a/ExpressionEngine/Functions/Implementations/CollectionFunctions/IntersectionFunction.cs b/ExpressionEngine/Functions/Implementations/CollectionFunctions/IntersectionFunction.cs index 0dfb58b..c78bcfb 100644 --- a/ExpressionEngine/Functions/Implementations/CollectionFunctions/IntersectionFunction.cs +++ b/ExpressionEngine/Functions/Implementations/CollectionFunctions/IntersectionFunction.cs @@ -17,7 +17,7 @@ public override ValueTask ExecuteFunction(params ValueContainer[ { ValueContainer.ValueType.Array => IntersectList(parameters), ValueContainer.ValueType.Object => IntersectDict(parameters), - _ => throw new PowerAutomateMockUpException( + _ => throw new ExpressionEngineException( $"Can only intersect Array and Object, not {parameters[0].Type()}.") }; } diff --git a/ExpressionEngine/Functions/Implementations/CollectionFunctions/LastFunction.cs b/ExpressionEngine/Functions/Implementations/CollectionFunctions/LastFunction.cs index 95639b3..b3c36b3 100644 --- a/ExpressionEngine/Functions/Implementations/CollectionFunctions/LastFunction.cs +++ b/ExpressionEngine/Functions/Implementations/CollectionFunctions/LastFunction.cs @@ -21,7 +21,7 @@ public override ValueTask ExecuteFunction(params ValueContainer[ value.GetValue().ToCharArray().Last().ToString())), ValueContainer.ValueType.Array => new ValueTask(new ValueContainer( value.GetValue>().Last())), - _ => throw new PowerAutomateMockUpException( + _ => throw new ExpressionEngineException( $"Empty expression can only operate on String or Array types, not {value.Type()}.") }; } diff --git a/ExpressionEngine/Functions/Implementations/CollectionFunctions/SkipFunction.cs b/ExpressionEngine/Functions/Implementations/CollectionFunctions/SkipFunction.cs index 23a1cee..7ddf037 100644 --- a/ExpressionEngine/Functions/Implementations/CollectionFunctions/SkipFunction.cs +++ b/ExpressionEngine/Functions/Implementations/CollectionFunctions/SkipFunction.cs @@ -20,7 +20,7 @@ public override ValueTask ExecuteFunction(params ValueContainer[ { ValueContainer.ValueType.Array => new ValueTask(new ValueContainer( value.GetValue>().Skip(count))), - _ => throw new PowerAutomateMockUpException( + _ => throw new ExpressionEngineException( $"Empty expression can only operate on String or Array types, not {value.Type()}.") }; } diff --git a/ExpressionEngine/Functions/Implementations/CollectionFunctions/TakeFunction.cs b/ExpressionEngine/Functions/Implementations/CollectionFunctions/TakeFunction.cs index 41bad0e..4b45981 100644 --- a/ExpressionEngine/Functions/Implementations/CollectionFunctions/TakeFunction.cs +++ b/ExpressionEngine/Functions/Implementations/CollectionFunctions/TakeFunction.cs @@ -20,7 +20,7 @@ public override ValueTask ExecuteFunction(params ValueContainer[ { ValueContainer.ValueType.Array => new ValueTask(new ValueContainer( value.GetValue>().Take(count))), - _ => throw new PowerAutomateMockUpException( + _ => throw new ExpressionEngineException( $"Empty expression can only operate on String or Array types, not {value.Type()}.") }; } diff --git a/ExpressionEngine/Functions/Implementations/CollectionFunctions/UnionFunction.cs b/ExpressionEngine/Functions/Implementations/CollectionFunctions/UnionFunction.cs index 5f735a9..4e487ef 100644 --- a/ExpressionEngine/Functions/Implementations/CollectionFunctions/UnionFunction.cs +++ b/ExpressionEngine/Functions/Implementations/CollectionFunctions/UnionFunction.cs @@ -17,7 +17,7 @@ public override async ValueTask ExecuteFunction(params ValueCont { ValueContainer.ValueType.Array => UnionList(parameters), ValueContainer.ValueType.Object => UnionDict(parameters), - _ => throw new PowerAutomateMockUpException( + _ => throw new ExpressionEngineException( $"Can only union Array and Object, not {parameters[0].Type()}.") }; } diff --git a/ExpressionEngine/Functions/Implementations/ConversionFunctions/ArrayFunction.cs b/ExpressionEngine/Functions/Implementations/ConversionFunctions/ArrayFunction.cs index ca814d0..5f1c348 100644 --- a/ExpressionEngine/Functions/Implementations/ConversionFunctions/ArrayFunction.cs +++ b/ExpressionEngine/Functions/Implementations/ConversionFunctions/ArrayFunction.cs @@ -15,7 +15,7 @@ public override ValueTask ExecuteFunction(params ValueContainer[ { ValueContainer.ValueType.String => new ValueTask( new ValueContainer(new[] {parameters[0]})), - _ => throw new PowerAutomateMockUpException( + _ => throw new ExpressionEngineException( $"Array function can only operate on strings, not {parameters[0].Type()}.") }; } diff --git a/ExpressionEngine/Functions/Implementations/ConversionFunctions/Base64Function.cs b/ExpressionEngine/Functions/Implementations/ConversionFunctions/Base64Function.cs index ed3d490..cdcfa20 100644 --- a/ExpressionEngine/Functions/Implementations/ConversionFunctions/Base64Function.cs +++ b/ExpressionEngine/Functions/Implementations/ConversionFunctions/Base64Function.cs @@ -17,7 +17,7 @@ public override ValueTask ExecuteFunction(params ValueContainer[ new ValueTask(new ValueContainer( System.Convert.ToBase64String( System.Text.Encoding.UTF8.GetBytes(parameters[0].GetValue())))), - _ => throw new PowerAutomateMockUpException( + _ => throw new ExpressionEngineException( $"Array function can only operate on strings, not {parameters[0].Type()}.") }; } diff --git a/ExpressionEngine/Functions/Implementations/ConversionFunctions/Base64ToBinaryFunction.cs b/ExpressionEngine/Functions/Implementations/ConversionFunctions/Base64ToBinaryFunction.cs index 72ddf5a..999aade 100644 --- a/ExpressionEngine/Functions/Implementations/ConversionFunctions/Base64ToBinaryFunction.cs +++ b/ExpressionEngine/Functions/Implementations/ConversionFunctions/Base64ToBinaryFunction.cs @@ -18,7 +18,7 @@ public override ValueTask ExecuteFunction(params ValueContainer[ ValueContainer.ValueType.String => new ValueTask(new ValueContainer(Convert.FromBase64String(parameters[0].GetValue()) .Aggregate("", (s, b) => s + Convert.ToString(b, 2).PadLeft(8, '0')))), - _ => throw new PowerAutomateMockUpException( + _ => throw new ExpressionEngineException( $"Array function can only operate on strings, not {parameters[0].Type()}.") }; } diff --git a/ExpressionEngine/Functions/Implementations/ConversionFunctions/Base64ToStringFunction.cs b/ExpressionEngine/Functions/Implementations/ConversionFunctions/Base64ToStringFunction.cs index 0aa81dc..0ed0a2b 100644 --- a/ExpressionEngine/Functions/Implementations/ConversionFunctions/Base64ToStringFunction.cs +++ b/ExpressionEngine/Functions/Implementations/ConversionFunctions/Base64ToStringFunction.cs @@ -17,7 +17,7 @@ public override ValueTask ExecuteFunction(params ValueContainer[ { ValueContainer.ValueType.String => new ValueTask(new ValueContainer(Encoding.UTF8.GetString(Convert.FromBase64String(parameters[0].GetValue())))), - _ => throw new PowerAutomateMockUpException( + _ => throw new ExpressionEngineException( $"Array function can only operate on strings, not {parameters[0].Type()}.") }; } diff --git a/ExpressionEngine/Functions/Implementations/ConversionFunctions/BinaryFunction.cs b/ExpressionEngine/Functions/Implementations/ConversionFunctions/BinaryFunction.cs index f93e032..effc92c 100644 --- a/ExpressionEngine/Functions/Implementations/ConversionFunctions/BinaryFunction.cs +++ b/ExpressionEngine/Functions/Implementations/ConversionFunctions/BinaryFunction.cs @@ -20,7 +20,7 @@ public override ValueTask ExecuteFunction(params ValueContainer[ new ValueTask(new ValueContainer(Encoding.UTF8 .GetBytes(parameters[0].GetValue()) .Aggregate("", (s, b) => s + Convert.ToString(b, 2).PadLeft(8, '0')))), - _ => throw new PowerAutomateMockUpException( + _ => throw new ExpressionEngineException( $"Array function can only operate on strings, not {parameters[0].Type()}.") }; } diff --git a/ExpressionEngine/Functions/Implementations/ConversionFunctions/BoolFunction.cs b/ExpressionEngine/Functions/Implementations/ConversionFunctions/BoolFunction.cs index db5b0ae..83eb7f8 100644 --- a/ExpressionEngine/Functions/Implementations/ConversionFunctions/BoolFunction.cs +++ b/ExpressionEngine/Functions/Implementations/ConversionFunctions/BoolFunction.cs @@ -21,7 +21,7 @@ public override ValueTask ExecuteFunction(params ValueContainer[ case "false": return new ValueTask(new ValueContainer(false)); default: - throw new PowerAutomateMockUpException( + throw new ExpressionEngineException( $"Can only convert 'true' or 'false' to bool, not {parameters[0].GetValue()}."); } case ValueContainer.ValueType.Integer: @@ -33,7 +33,7 @@ public override ValueTask ExecuteFunction(params ValueContainer[ case ValueContainer.ValueType.Boolean: return new ValueTask(parameters[0]); default: - throw new PowerAutomateMockUpException( + throw new ExpressionEngineException( $"Array function can only operate on strings, not {parameters[0].Type()}."); } } diff --git a/ExpressionEngine/Functions/Implementations/ConversionFunctions/DataUriFunction.cs b/ExpressionEngine/Functions/Implementations/ConversionFunctions/DataUriFunction.cs index bf4c7d3..c28abd4 100644 --- a/ExpressionEngine/Functions/Implementations/ConversionFunctions/DataUriFunction.cs +++ b/ExpressionEngine/Functions/Implementations/ConversionFunctions/DataUriFunction.cs @@ -22,7 +22,7 @@ public override ValueTask ExecuteFunction(params ValueContainer[ ValueContainer.ValueType.String => new ValueTask(new ValueContainer( $"data:text/plain;charset=utf-8;base64,{System.Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(parameters[0].GetValue()))}")), - _ => throw new PowerAutomateMockUpException( + _ => throw new ExpressionEngineException( $"Array function can only operate on strings, not {parameters[0].Type()}.") }; } diff --git a/ExpressionEngine/Functions/Implementations/ConversionFunctions/DataUriToBinaryFunction.cs b/ExpressionEngine/Functions/Implementations/ConversionFunctions/DataUriToBinaryFunction.cs index 37f1ab8..9406318 100644 --- a/ExpressionEngine/Functions/Implementations/ConversionFunctions/DataUriToBinaryFunction.cs +++ b/ExpressionEngine/Functions/Implementations/ConversionFunctions/DataUriToBinaryFunction.cs @@ -25,7 +25,7 @@ public override ValueTask ExecuteFunction(params ValueContainer[ ValueContainer.ValueType.String => new ValueTask(new ValueContainer(Encoding.UTF8.GetBytes(parameters[0].GetValue()) .Aggregate("", (s, b) => s + Convert.ToString(b, 2).PadLeft(8, '0')))), - _ => throw new PowerAutomateMockUpException( + _ => throw new ExpressionEngineException( $"Array function can only operate on strings, not {parameters[0].Type()}.") }; } diff --git a/ExpressionEngine/Functions/Implementations/StringFunctions/AuxiliaryMethods.cs b/ExpressionEngine/Functions/Implementations/StringFunctions/AuxiliaryMethods.cs index 4431967..4915f9f 100644 --- a/ExpressionEngine/Functions/Implementations/StringFunctions/AuxiliaryMethods.cs +++ b/ExpressionEngine/Functions/Implementations/StringFunctions/AuxiliaryMethods.cs @@ -6,7 +6,7 @@ public static string VcIsString(ValueContainer vc) { return vc.Type() == ValueContainer.ValueType.String ? vc.GetValue() - : throw new PowerAutomateMockUpException("ValueContainer must be of type string."); + : throw new ExpressionEngineException("ValueContainer must be of type string."); } } } \ No newline at end of file diff --git a/ExpressionEngine/Functions/Implementations/StringFunctions/FormatNumberFunction.cs b/ExpressionEngine/Functions/Implementations/StringFunctions/FormatNumberFunction.cs index 989bd37..48e5c55 100644 --- a/ExpressionEngine/Functions/Implementations/StringFunctions/FormatNumberFunction.cs +++ b/ExpressionEngine/Functions/Implementations/StringFunctions/FormatNumberFunction.cs @@ -40,7 +40,7 @@ public override ValueTask ExecuteFunction(params ValueContainer[ return new ValueTask(new ValueContainer(floatValue.ToString(format, CultureInfo.CreateSpecificCulture(locale)))); } - throw new PowerAutomateMockUpException("Expected an numeric value when formatting numbers."); + throw new ExpressionEngineException("Expected an numeric value when formatting numbers."); } } } \ No newline at end of file diff --git a/ExpressionEngine/Functions/Implementations/StringFunctions/GuidFunction.cs b/ExpressionEngine/Functions/Implementations/StringFunctions/GuidFunction.cs index 1661a77..facf039 100644 --- a/ExpressionEngine/Functions/Implementations/StringFunctions/GuidFunction.cs +++ b/ExpressionEngine/Functions/Implementations/StringFunctions/GuidFunction.cs @@ -24,7 +24,7 @@ public override ValueTask ExecuteFunction(params ValueContainer[ var format = AuxiliaryMethods.VcIsString(parameters[0]); if (!new[] {"n", "d", "b", "p", "x"}.Contains(format.ToLower())) { - throw new PowerAutomateMockUpException($"The given format, {format}, is not recognized."); + throw new ExpressionEngineException($"The given format, {format}, is not recognized."); } return new ValueTask(new ValueContainer(Guid.NewGuid().ToString(format.ToUpper()))); diff --git a/ExpressionEngine/Functions/Implementations/StringFunctions/SubstringFunction.cs b/ExpressionEngine/Functions/Implementations/StringFunctions/SubstringFunction.cs index e40aef9..987d3cb 100644 --- a/ExpressionEngine/Functions/Implementations/StringFunctions/SubstringFunction.cs +++ b/ExpressionEngine/Functions/Implementations/StringFunctions/SubstringFunction.cs @@ -27,7 +27,7 @@ public override ValueTask ExecuteFunction(params ValueContainer[ if (startIndex + length > str.Length) { - throw new PowerAutomateMockUpException( + throw new ExpressionEngineException( "The template language function 'substring' parameters are out of range: 'start index' " + "and 'length' must be non-negative integers and their sum must be no larger than the length of " + "the string."); diff --git a/ExpressionEngine/PowerAutomateMockUpException.cs b/ExpressionEngine/PowerAutomateMockUpException.cs deleted file mode 100644 index d1be350..0000000 --- a/ExpressionEngine/PowerAutomateMockUpException.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; - -namespace ExpressionEngine -{ - internal class PowerAutomateMockUpException : Exception - { - public PowerAutomateMockUpException(string couldNotParseJtokenToValuecontainer) - { - throw new NotImplementedException(); - } - } -} \ No newline at end of file diff --git a/ExpressionEngine/ValueContainer.cs b/ExpressionEngine/ValueContainer.cs index 4400a53..850326b 100644 --- a/ExpressionEngine/ValueContainer.cs +++ b/ExpressionEngine/ValueContainer.cs @@ -213,7 +213,7 @@ public Dictionary AsDict() return GetValue>(); } - throw new PowerAutomateMockUpException("Can't get none object value container as dict."); + throw new ExpressionEngineException("Can't get none object value container as dict."); } public override string ToString() @@ -412,7 +412,7 @@ private static async ValueTask JsonToValueContainer(JToken json, case JValue jValue: if (jValue.HasValues) { - throw new PowerAutomateMockUpException( + throw new ExpressionEngineException( "When parsing JToken to ValueContainer, the JToken as JValue can only contain one value."); } @@ -427,11 +427,11 @@ private static async ValueTask JsonToValueContainer(JToken json, JTokenType.String => new ValueContainer(jValue.Value()), JTokenType.None => new ValueContainer(), JTokenType.Guid => new ValueContainer(jValue.Value().ToString()), - _ => throw new PowerAutomateMockUpException( + _ => throw new ExpressionEngineException( $"{jValue.Type} is not yet supported in ValueContainer conversion") }; default: - throw new PowerAutomateMockUpException("Could not parse JToken to ValueContainer."); + throw new ExpressionEngineException("Could not parse JToken to ValueContainer."); } } @@ -443,7 +443,7 @@ private static ValueContainer JArrayToValueContainer(JArray json) { if (jToken.GetType() != typeof(JValue)) { - throw new PowerAutomateMockUpException("Json can only contain arrays of primitive types."); + throw new ExpressionEngineException("Json can only contain arrays of primitive types."); } var t = (JValue) jToken; @@ -462,7 +462,7 @@ private static ValueContainer JArrayToValueContainer(JArray json) list.Add(new ValueContainer(d)); break; default: - throw new PowerAutomateMockUpException( + throw new ExpressionEngineException( $"Type {t.Value.GetType()} is not recognized when converting Json to ValueContainer."); } } diff --git a/Test/IndexTest.cs b/Test/IndexTest.cs index d372868..bbd7681 100644 --- a/Test/IndexTest.cs +++ b/Test/IndexTest.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Threading.Tasks; using ExpressionEngine; using ExpressionEngine.Functions.Base; @@ -93,6 +92,55 @@ public async Task Test4() Assert.AreEqual(ValueContainer.ValueType.Boolean, output.Type()); Assert.AreEqual(true, output.GetValue()); } + + + [Test] + public async Task Test5() + { + const string str = "@variables().account"; + var ee = _serviceProvider.GetRequiredService(); + + var output = await ee.ParseToValueContainer(str); + + Assert.AreEqual(ValueContainer.ValueType.Object, output.Type()); + Assert.AreEqual("John Doe", output.AsDict()["name"].GetValue()); + } + [Test] + public async Task Test6() + { + const string str = "@{variables().account.name}"; + var ee = _serviceProvider.GetRequiredService(); + + var output = await ee.ParseToValueContainer(str); + + Assert.AreEqual(ValueContainer.ValueType.String, output.Type()); + Assert.AreEqual("John Doe", output.GetValue()); + } + + [Test] + public async Task Test7() + { + const string str = "@variables()['account']"; + var ee = _serviceProvider.GetRequiredService(); + + var output = await ee.ParseToValueContainer(str); + + Assert.AreEqual(ValueContainer.ValueType.Object, output.Type()); + Assert.AreEqual("John Doe", output.AsDict()["name"].GetValue()); + } + + + [Test] + public async Task Test8() + { + const string str = "@{variables()['account']['name']}"; + var ee = _serviceProvider.GetRequiredService(); + + var output = await ee.ParseToValueContainer(str); + + Assert.AreEqual(ValueContainer.ValueType.String, output.Type()); + Assert.AreEqual("John Doe", output.GetValue()); + } } } \ No newline at end of file