diff --git a/src/Altinn.App.Core/Internal/Expressions/ExpressionEvaluator.cs b/src/Altinn.App.Core/Internal/Expressions/ExpressionEvaluator.cs index 8f4d5d8735..8af17e5afd 100644 --- a/src/Altinn.App.Core/Internal/Expressions/ExpressionEvaluator.cs +++ b/src/Altinn.App.Core/Internal/Expressions/ExpressionEvaluator.cs @@ -11,7 +11,7 @@ namespace Altinn.App.Core.Internal.Expressions; /// /// Static class used to evaluate expressions. Holds the implementation for all expression functions. /// -public static class ExpressionEvaluator +public static partial class ExpressionEvaluator { /// /// Shortcut for evaluating a boolean expression on a given property on a @@ -127,6 +127,10 @@ internal static async Task EvaluateExpression_internal( ExpressionFunction.argv => Argv(args, positionalArguments), ExpressionFunction.gatewayAction => state.GetGatewayAction(), ExpressionFunction.language => state.GetLanguage(), + ExpressionFunction.plus => Plus(args), + ExpressionFunction.minus => Minus(args), + ExpressionFunction.multiply => Multiply(args), + ExpressionFunction.divide => Divide(args), ExpressionFunction.INVALID => throw new ExpressionEvaluatorTypeErrorException( $"Function {expr.Args.FirstOrDefault()} not implemented in backend {expr}" ), @@ -810,7 +814,7 @@ private static (double?, double?) PrepareNumericArgs(ExpressionValue[] args) { if (args.Length != 2) { - throw new ExpressionEvaluatorTypeErrorException("Invalid number of args for compare"); + throw new ExpressionEvaluatorTypeErrorException("Invalid number of args"); } var a = PrepareNumericArg(args[0]); @@ -861,11 +865,12 @@ private static ExpressionValue IfImpl(ExpressionValue[] args) ); } - private static readonly Regex _numberRegex = new Regex(@"^-?\d+(\.\d+)?$"); - + /// + /// Parses a number from a string representation. + /// internal static double? ParseNumber(string s, bool throwException = true) { - if (_numberRegex.IsMatch(s) && double.TryParse(s, NumberStyles.Any, CultureInfo.InvariantCulture, out var d)) + if (NumberRegex().IsMatch(s) && double.TryParse(s, NumberStyles.Any, CultureInfo.InvariantCulture, out var d)) { return d; } @@ -888,6 +893,30 @@ private static bool LessThan(ExpressionValue[] args) return a < b; // Actual implementation } + private static double? Plus(ExpressionValue[] args) + { + var (a, b) = PrepareNumericArgs(args); + return PerformArithmetic(a, b, (x, y) => x + y); + } + + private static double? Minus(ExpressionValue[] args) + { + var (a, b) = PrepareNumericArgs(args); + return PerformArithmetic(a, b, (x, y) => x - y); + } + + private static double? Multiply(ExpressionValue[] args) + { + var (a, b) = PrepareNumericArgs(args); + return PerformArithmetic(a, b, (x, y) => x * y); + } + + private static double? Divide(ExpressionValue[] args) + { + var (a, b) = PrepareNumericArgs(args); + return PerformArithmetic(a, b, (x, y) => x / y); + } + private static bool LessThanEq(ExpressionValue[] args) { var (a, b) = PrepareNumericArgs(args); @@ -960,4 +989,41 @@ private static ExpressionValue Argv(ExpressionValue[] args, ExpressionValue[]? p return positionalArguments[index.Value]; } + + /// + /// Performs arithmetic operation using decimal precision to avoid floating point precision issues. + /// Converts doubles to decimal, performs the operation, and converts back to double. + /// + /// First operand + /// Second operand + /// Function that performs the arithmetic operation on two decimals + /// Result of the operation as double, or null if any operand is null + private static double? PerformArithmetic(double? a, double? b, Func operation) + { + if (a.HasValue is false || b.HasValue is false) + { + return null; + } + + try + { + var aDecimal = (decimal)a.Value; + var bDecimal = (decimal)b.Value; + var result = operation(aDecimal, bDecimal); + return (double)result; + } + catch (OverflowException) + { + throw new ExpressionEvaluatorTypeErrorException( + $"Arithmetic overflow: {a.Value} and {b.Value} or operation on them exceeds the supported range" + ); + } + catch (DivideByZeroException) + { + throw new ExpressionEvaluatorTypeErrorException("The second argument is 0, cannot divide by 0"); + } + } + + [GeneratedRegex(@"^[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?$")] + private static partial Regex NumberRegex(); } diff --git a/src/Altinn.App.Core/Internal/Expressions/ExpressionValue.cs b/src/Altinn.App.Core/Internal/Expressions/ExpressionValue.cs index be4e2d351c..225e0a31b3 100644 --- a/src/Altinn.App.Core/Internal/Expressions/ExpressionValue.cs +++ b/src/Altinn.App.Core/Internal/Expressions/ExpressionValue.cs @@ -141,9 +141,7 @@ public static ExpressionValue FromObject(object? value) uint numberValue => numberValue, long numberValue => numberValue, ulong numberValue => numberValue, - decimal numberValue => - (double?)numberValue // expressions uses double which needs an explicit cast - , + decimal numberValue => (double?)numberValue, // expressions uses double which needs an explicit cast DateTime dateTimeValue => JsonSerializer .Serialize(dateTimeValue, _unsafeSerializerOptionsForSerializingDates) .Trim( @@ -560,7 +558,7 @@ public bool TryDeserialize(Type type, out object? result) try { var json = ToString(); - result = JsonSerializer.Deserialize(json, type, _unsafeSerializerOptionsForSerializingDates); + result = JsonSerializer.Deserialize(json, type); return true; } catch (JsonException) diff --git a/src/Altinn.App.Core/Models/Expressions/ExpressionFunction.cs b/src/Altinn.App.Core/Models/Expressions/ExpressionFunction.cs index f799c95a9f..75d841ac41 100644 --- a/src/Altinn.App.Core/Models/Expressions/ExpressionFunction.cs +++ b/src/Altinn.App.Core/Models/Expressions/ExpressionFunction.cs @@ -205,4 +205,24 @@ public enum ExpressionFunction /// If no translations exist for the current language, we will use the resources for "nb" /// text, + + /// + /// Adding numbers. Must be numeric values. + /// + plus, + + /// + /// Subtracting all preceding values from the first. Must be numeric values. + /// + minus, + + /// + /// Multiplying numbers. Must be numeric values. + /// + multiply, + + /// + /// Divide numbers. Must be numeric values. + /// + divide, } diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/ExpressionTestCaseRoot.cs b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/ExpressionTestCaseRoot.cs index d1a0d9de3b..a45da8a56f 100644 --- a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/ExpressionTestCaseRoot.cs +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/ExpressionTestCaseRoot.cs @@ -10,6 +10,16 @@ namespace Altinn.App.Core.Tests.LayoutExpressions.CommonTests; public class ExpressionTestCaseRoot { + public ExpressionTestCaseRoot(TestCaseItem testCaseItem) + { + Name = testCaseItem.Name; + Expression = testCaseItem.Expression; + Expects = testCaseItem.Expects; + ExpectsFailure = testCaseItem.ExpectsFailure; + } + + public ExpressionTestCaseRoot() { } + [JsonIgnore] public string? Filename { get; set; } @@ -42,6 +52,9 @@ public class ExpressionTestCaseRoot public class TestCaseItem { + [JsonPropertyName("name")] + public string? Name { get; set; } + [JsonPropertyName("expression")] public required Expression Expression { get; set; } diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/TestFunctions.cs b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/TestFunctions.cs index ec7c206c8e..0db83c6c7d 100644 --- a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/TestFunctions.cs +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/TestFunctions.cs @@ -203,6 +203,26 @@ public TestFunctions(ITestOutputHelper output) [SharedTest("stringLength")] public async Task StringLength_Theory(string testName, string folder) => await RunTestCase(testName, folder); + [Theory] + [SharedTestCases("plus")] + public async Task Plus_Theory(string testName, ExpressionTestCaseRoot.TestCaseItem testCaseItem) => + await RunTestCase(testName, new ExpressionTestCaseRoot(testCaseItem)); + + [Theory] + [SharedTestCases("minus")] + public async Task Minus_Theory(string testName, ExpressionTestCaseRoot.TestCaseItem testCaseItem) => + await RunTestCase(testName, new ExpressionTestCaseRoot(testCaseItem)); + + [Theory] + [SharedTestCases("multiply")] + public async Task Multiply_Theory(string testName, ExpressionTestCaseRoot.TestCaseItem testCaseItem) => + await RunTestCase(testName, new ExpressionTestCaseRoot(testCaseItem)); + + [Theory] + [SharedTestCases("divide")] + public async Task Divide_Theory(string testName, ExpressionTestCaseRoot.TestCaseItem testCaseItem) => + await RunTestCase(testName, new ExpressionTestCaseRoot(testCaseItem)); + [Theory] [SharedTest("round")] public async Task Round_Theory(string testName, string folder) => await RunTestCase(testName, folder); @@ -237,10 +257,15 @@ private static async Task LoadTestCase(string file, stri private async Task RunTestCase(string testName, string folder) { var test = await LoadTestCase(testName, folder); - _output.WriteLine(test.Name); + await RunTestCase(testName, test); + } + + private async Task RunTestCase(string testName, ExpressionTestCaseRoot test) + { + _output.WriteLine(testName); _output.WriteLine($"{test.Folder}{Path.DirectorySeparatorChar}{test.Filename}"); - _output.WriteLine(test.RawJson); - _output.WriteLine(test.FullPath); + _output.WriteLine(test.RawJson ?? ""); + _output.WriteLine(test.FullPath ?? ""); IInstanceDataAccessor dataAccessor; List dataTypes = new(); @@ -316,16 +341,16 @@ private async Task RunTestCase(string testName, string folder) componentModel = new LayoutModel([layout], null); } - var appRewourcesMock = new Mock(MockBehavior.Strict); + var appResourcesMock = new Mock(MockBehavior.Strict); var language = test.ProfileSettings?.Language ?? "nb"; - appRewourcesMock + appResourcesMock .Setup(ar => ar.GetTexts(It.IsAny(), It.IsAny(), language)) .ReturnsAsync(new TextResource() { Resources = test.TextResources ?? [] }); var translationService = new TranslationService( new Core.Models.AppIdentifier("org", "app"), - appRewourcesMock.Object, + appResourcesMock.Object, FakeLoggerXunit.Get(_output) ); @@ -385,6 +410,7 @@ private async Task RunTestCaseItem( object?[]? positionalArguments ) { + _output.WriteLine(test.Name ?? ""); if (test.ExpectsFailure is not null) { _output.WriteLine($"Expecting failure: {test.ExpectsFailure}"); @@ -422,7 +448,6 @@ private async Task RunTestCaseItem( break; case JsonValueKind.True: Assert.True(result as bool?); - result.Should().Be(true); break; case JsonValueKind.False: Assert.False(result as bool?); @@ -457,7 +482,10 @@ public void Ensure_tests_For_All_Folders() var testMethods = this.GetType() .GetMethods() .Select(m => - m.CustomAttributes.FirstOrDefault(ca => ca.AttributeType == typeof(SharedTestAttribute)) + m.CustomAttributes.FirstOrDefault(ca => + ca.AttributeType == typeof(SharedTestAttribute) + || ca.AttributeType == typeof(SharedTestCasesAttribute) + ) ?.ConstructorArguments.FirstOrDefault() .Value ) @@ -473,3 +501,7 @@ public class SharedTestAttribute(string folder) : FileNamesInFolderDataAttribute( Path.Join("LayoutExpressions", "CommonTests", "shared-tests", "functions", folder) ) { } + +// Can be used when you only want to run the tests listed in the testCases array in the json file +public class SharedTestCasesAttribute(string folder) + : TestCasesAttribute(Path.Join("LayoutExpressions", "CommonTests", "shared-tests", "functions", folder)) { } diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/divide/divide.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/divide/divide.json new file mode 100644 index 0000000000..33d1fa8c57 --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/divide/divide.json @@ -0,0 +1,195 @@ +{ + "name": "Divide tests", + "testCases": [ + { + "name": "Should divide the first argument with the second", + "expression": ["divide", 0.1, 0.2], + "expects": 0.5 + }, + { + "name": "Should divide two negative numbers yielding positive result", + "expression": ["divide", -0.1, -0.2], + "expects": 0.5 + }, + { + "name": "Should return null when both of the arguments are null", + "expression": ["divide", null, null], + "expects": null + }, + { + "name": "Should return null when one of the arguments is null [null, decimal]", + "expression": ["divide", null, 2.1], + "expects": null + }, + { + "name": "Should return null when one of the arguments is null [decimal, null]", + "expression": ["divide", 2.1, null], + "expects": null + }, + { + "name": "Should divide two integers", + "expression": ["divide", 30, 6], + "expects": 5 + }, + { + "name": "Should divide [float, integer]", + "expression": ["divide", 30.0, 6], + "expects": 5.0 + }, + { + "name": "Should divide [string, integer] when string is valid number", + "expression": ["divide", "30", 6], + "expects": 5 + }, + { + "name": "Should divide [string, float] when string is valid number", + "expression": ["divide", "22.0", 4.0], + "expects": 5.5 + }, + { + "name": "Should handle dividing zero by a number", + "expression": ["divide", 0, 42], + "expects": 0 + }, + { + "name": "Should divide negative by positive", + "expression": ["divide", -30, 6], + "expects": -5 + }, + { + "name": "Should divide two negative numbers", + "expression": ["divide", -30, -6], + "expects": 5 + }, + { + "name": "Should divide numbers in scientific notation", + "expression": ["divide", 6e3, 2e3], + "expects": 3 + }, + { + "name": "Should divide numbers with negative exponents", + "expression": ["divide", 6e-3, 2e-3], + "expects": 3 + }, + { + "name": "Should divide scientific notation by regular number", + "expression": ["divide", 5e2, 10], + "expects": 50 + }, + { + "name": "Should fail with invalid string that cannot be parsed as number", + "expression": ["divide", 100, "not a number"], + "expectsFailure": "Expected number, got value \"not a number\"" + }, + { + "name": "Should fail with string with no decimals after dot", + "expression": ["divide", "55.", 5], + "expectsFailure": "Expected number, got value \"55.\"" + }, + { + "name": "Should handle very large numbers within the safe range", + "expression": ["divide", 1000000000000, 1000000], + "expects": 1000000 + }, + { + "name": "Should handle very large number formatted as string", + "expression": ["divide", "999999999999999", 3], + "expects": 333333333333333 + }, + { + "name": "Should handle very small numbers", + "expression": ["divide", 0.00000001, 0.0001], + "expects": 0.0001 + }, + { + "name": "Returns expected value for inputs that would return different result when treated as 64-bit binary floats", + "expression": ["divide", 0.00000001, 0.0001], + "expects": 0.0001 + }, + { + "name": "Should divide string scientific notation with plus sign in front of coefficient", + "expression": ["divide", "+5E2", 10], + "expects": 50 + }, + { + "name": "Should divide string scientific notation with plus sign in front of exponent", + "expression": ["divide", "5E+2", 10], + "expects": 50 + }, + { + "name": "Should divide string scientific notation with negative sign in front of coefficient", + "expression": ["divide", "-5E2", 10], + "expects": -50 + }, + { + "name": "Should divide string scientific notation with negative sign in front of exponent", + "expression": ["divide", "5e-2", 10], + "expects": 0.005 + }, + { + "name": "Should divide string scientific notation by number", + "expression": ["divide", "5E2", 10], + "expects": 50 + }, + { + "name": "Should divide string scientific notation with no whole number part by number", + "expression": ["divide", ".5e2", 10], + "expects": 5 + }, + { + "name": "Should divide string scientific notation equivalent to 0 by number", + "expression": ["divide", "0e0", 10], + "expects": 0 + }, + { + "name": "Should throw exception when string scientific notation has negative sign before the E", + "expression": ["divide", "5-E2", 10], + "expectsFailure": "Expected number, got value \"5-E2\"" + }, + { + "name": "Should throw exception when string scientific notation has plus sign before the E", + "expression": ["divide", "5+E2", 10], + "expectsFailure": "Expected number, got value \"5+E2\"" + }, + { + "name": "Should throw exception when string scientific notation is missing the exponent", + "expression": ["divide", "5e", 10], + "expectsFailure": "Expected number, got value \"5e\"" + }, + { + "name": "Should throw exception when string scientific notation is missing the coefficient", + "expression": ["divide", "e2", 10], + "expectsFailure": "Expected number, got value \"e2\"" + }, + { + "name": "Should throw exception when less than two arguments are provided", + "expression": ["divide", 2.1], + "expectsFailure": "Invalid" + }, + { + "name": "Should throw exception when more than two arguments are present", + "expression": ["divide", 0.1, 0.2, 15, 1.50], + "expectsFailure": "Invalid" + }, + { + "name": "Should divide negative by positive decimal", + "expression": ["divide", -0.1, 0.2], + "expects": -0.5 + }, + { + "name": "Should return null when dividend is null and divisor is zero", + "expression": ["divide", null, 0], + "expects": null + }, + { + "name": "Should throw exception when trying to divide by zero", + "expression": ["divide", 15, 0], + "expectsFailure": "The second argument is 0, cannot divide by 0" + }, + { + "name": "Should fail with [boolean, integer]", + "expression": ["divide", true, 100], + "expectsFailure": "Expected number, got value true" + } + ] +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThan/error-sci-not-string-format-1.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThan/error-sci-not-string-format-1.json new file mode 100644 index 0000000000..4f42f781a5 --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThan/error-sci-not-string-format-1.json @@ -0,0 +1,5 @@ +{ + "name": "Should throw exception when string scientific notation has plus sign before the E", + "expression": ["greaterThan", "5+E2", 10], + "expectsFailure": "Expected number, got value \"5+E2\"" +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThan/error-sci-not-string-format-2.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThan/error-sci-not-string-format-2.json new file mode 100644 index 0000000000..e6dccb696a --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThan/error-sci-not-string-format-2.json @@ -0,0 +1,5 @@ +{ + "name": "Should throw exception when string scientific notation has negative sign before the E", + "expression": ["greaterThan", "5-E2", 10], + "expectsFailure": "Expected number, got value \"5-E2\"" +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThan/error-sci-not-string-no-coefficient.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThan/error-sci-not-string-no-coefficient.json new file mode 100644 index 0000000000..4de19c0b4a --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThan/error-sci-not-string-no-coefficient.json @@ -0,0 +1,5 @@ +{ + "name": "Should throw exception when string scientific notation is missing the coefficient", + "expression": ["greaterThan", "e2", 10], + "expectsFailure": "Expected number, got value \"e2\"" +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThan/error-sci-not-string-no-exponent.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThan/error-sci-not-string-no-exponent.json new file mode 100644 index 0000000000..83659fb95f --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThan/error-sci-not-string-no-exponent.json @@ -0,0 +1,5 @@ +{ + "name": "Should throw exception when string scientific notation is missing the exponent", + "expression": ["greaterThan", "5e", 10], + "expectsFailure": "Expected number, got value \"5e\"" +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThan/sci-notation-negative-exponents.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThan/sci-notation-negative-exponents.json new file mode 100644 index 0000000000..4520d9d12b --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThan/sci-notation-negative-exponents.json @@ -0,0 +1,5 @@ +{ + "name": "Should work with numbers with negative exponents (true)", + "expression": ["greaterThan", 5e-3, 2e-3], + "expects": true +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThan/sci-notation-numbers.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThan/sci-notation-numbers.json new file mode 100644 index 0000000000..e6a176020f --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThan/sci-notation-numbers.json @@ -0,0 +1,5 @@ +{ + "name": "Should work with numbers in scientific notation (true)", + "expression": ["greaterThan", 5e3, 2e3], + "expects": true +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThan/sci-notation-with-regular.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThan/sci-notation-with-regular.json new file mode 100644 index 0000000000..1e41f625b9 --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThan/sci-notation-with-regular.json @@ -0,0 +1,5 @@ +{ + "name": "Should work with scientific notation and regular number (true)", + "expression": ["greaterThan", 1e2, 50], + "expects": true +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThan/sci-string-basic.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThan/sci-string-basic.json new file mode 100644 index 0000000000..3e0602ee42 --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThan/sci-string-basic.json @@ -0,0 +1,5 @@ +{ + "name": "Should parse string scientific notation (true)", + "expression": ["greaterThan", "5E2", 400], + "expects": true +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThan/sci-string-negative-coefficient.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThan/sci-string-negative-coefficient.json new file mode 100644 index 0000000000..721fa501bc --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThan/sci-string-negative-coefficient.json @@ -0,0 +1,5 @@ +{ + "name": "Should parse string scientific notation with negative sign in front of coefficient (true)", + "expression": ["greaterThan", 10, "-5E2"], + "expects": true +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThan/sci-string-negative-exponent.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThan/sci-string-negative-exponent.json new file mode 100644 index 0000000000..62ab060874 --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThan/sci-string-negative-exponent.json @@ -0,0 +1,5 @@ +{ + "name": "Should parse string scientific notation with negative sign in front of exponent (false)", + "expression": ["greaterThan", "5e-2", 10], + "expects": false +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThan/sci-string-no-whole.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThan/sci-string-no-whole.json new file mode 100644 index 0000000000..7cd772c145 --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThan/sci-string-no-whole.json @@ -0,0 +1,5 @@ +{ + "name": "Should parse string scientific notation with no whole number part (false)", + "expression": ["greaterThan", ".5e2", 100], + "expects": false +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThan/sci-string-plus-coefficient.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThan/sci-string-plus-coefficient.json new file mode 100644 index 0000000000..471c501fd5 --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThan/sci-string-plus-coefficient.json @@ -0,0 +1,5 @@ +{ + "name": "Should parse string scientific notation with plus sign in front of coefficient (true)", + "expression": ["greaterThan", "+5E2", 400], + "expects": true +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThan/sci-string-plus-exponent.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThan/sci-string-plus-exponent.json new file mode 100644 index 0000000000..47e5e903d0 --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThan/sci-string-plus-exponent.json @@ -0,0 +1,5 @@ +{ + "name": "Should parse string scientific notation with plus sign in front of exponent (true)", + "expression": ["greaterThan", "5E+2", 400], + "expects": true +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThan/sci-string-zero.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThan/sci-string-zero.json new file mode 100644 index 0000000000..b4212c9640 --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThan/sci-string-zero.json @@ -0,0 +1,5 @@ +{ + "name": "Should parse string scientific notation equivalent to 0 (false)", + "expression": ["greaterThan", "0e0", 10], + "expects": false +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThanEq/error-sci-not-string-format-1.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThanEq/error-sci-not-string-format-1.json new file mode 100644 index 0000000000..6f0e47ea10 --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThanEq/error-sci-not-string-format-1.json @@ -0,0 +1,5 @@ +{ + "name": "Should throw exception when string scientific notation has plus sign before the E", + "expression": ["greaterThanEq", "5+E2", 10], + "expectsFailure": "Expected number, got value \"5+E2\"" +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThanEq/error-sci-not-string-format-2.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThanEq/error-sci-not-string-format-2.json new file mode 100644 index 0000000000..8be5e3e88f --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThanEq/error-sci-not-string-format-2.json @@ -0,0 +1,5 @@ +{ + "name": "Should throw exception when string scientific notation has negative sign before the E", + "expression": ["greaterThanEq", "5-E2", 10], + "expectsFailure": "Expected number, got value \"5-E2\"" +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThanEq/error-sci-not-string-no-coefficient.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThanEq/error-sci-not-string-no-coefficient.json new file mode 100644 index 0000000000..8eeb9e41a9 --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThanEq/error-sci-not-string-no-coefficient.json @@ -0,0 +1,5 @@ +{ + "name": "Should throw exception when string scientific notation is missing the coefficient", + "expression": ["greaterThanEq", "e2", 10], + "expectsFailure": "Expected number, got value \"e2\"" +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThanEq/error-sci-not-string-no-exponent.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThanEq/error-sci-not-string-no-exponent.json new file mode 100644 index 0000000000..10cbc2835a --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThanEq/error-sci-not-string-no-exponent.json @@ -0,0 +1,5 @@ +{ + "name": "Should throw exception when string scientific notation is missing the exponent", + "expression": ["greaterThanEq", "5e", 10], + "expectsFailure": "Expected number, got value \"5e\"" +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThanEq/sci-notation-negative-exponents.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThanEq/sci-notation-negative-exponents.json new file mode 100644 index 0000000000..0fb42437fb --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThanEq/sci-notation-negative-exponents.json @@ -0,0 +1,5 @@ +{ + "name": "Should work with numbers with negative exponents (true)", + "expression": ["greaterThanEq", 5e-3, 2e-3], + "expects": true +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThanEq/sci-notation-numbers.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThanEq/sci-notation-numbers.json new file mode 100644 index 0000000000..c9977d6281 --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThanEq/sci-notation-numbers.json @@ -0,0 +1,5 @@ +{ + "name": "Should work with numbers in scientific notation (true)", + "expression": ["greaterThanEq", 5e3, 2e3], + "expects": true +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThanEq/sci-notation-with-regular.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThanEq/sci-notation-with-regular.json new file mode 100644 index 0000000000..77a9394fe0 --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThanEq/sci-notation-with-regular.json @@ -0,0 +1,5 @@ +{ + "name": "Should work with scientific notation and regular number (true)", + "expression": ["greaterThanEq", 1e2, 50], + "expects": true +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThanEq/sci-string-basic.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThanEq/sci-string-basic.json new file mode 100644 index 0000000000..50e9ccf1b4 --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThanEq/sci-string-basic.json @@ -0,0 +1,5 @@ +{ + "name": "Should parse string scientific notation (true)", + "expression": ["greaterThanEq", "5E2", 400], + "expects": true +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThanEq/sci-string-negative-coefficient.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThanEq/sci-string-negative-coefficient.json new file mode 100644 index 0000000000..ecadea0d50 --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThanEq/sci-string-negative-coefficient.json @@ -0,0 +1,5 @@ +{ + "name": "Should parse string scientific notation with negative sign in front of coefficient (true)", + "expression": ["greaterThanEq", 10, "-5E2"], + "expects": true +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThanEq/sci-string-negative-exponent.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThanEq/sci-string-negative-exponent.json new file mode 100644 index 0000000000..7fbee498e3 --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThanEq/sci-string-negative-exponent.json @@ -0,0 +1,5 @@ +{ + "name": "Should parse string scientific notation with negative sign in front of exponent (false)", + "expression": ["greaterThanEq", "5e-2", 10], + "expects": false +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThanEq/sci-string-no-whole.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThanEq/sci-string-no-whole.json new file mode 100644 index 0000000000..1dc7c51c6a --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThanEq/sci-string-no-whole.json @@ -0,0 +1,5 @@ +{ + "name": "Should parse string scientific notation with no whole number part (false)", + "expression": ["greaterThanEq", ".5e2", 100], + "expects": false +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThanEq/sci-string-plus-coefficient.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThanEq/sci-string-plus-coefficient.json new file mode 100644 index 0000000000..b9fa7d39fd --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThanEq/sci-string-plus-coefficient.json @@ -0,0 +1,5 @@ +{ + "name": "Should parse string scientific notation with plus sign in front of coefficient (true)", + "expression": ["greaterThanEq", "+5E2", 400], + "expects": true +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThanEq/sci-string-plus-exponent.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThanEq/sci-string-plus-exponent.json new file mode 100644 index 0000000000..dab61c5133 --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThanEq/sci-string-plus-exponent.json @@ -0,0 +1,5 @@ +{ + "name": "Should parse string scientific notation with plus sign in front of exponent (true)", + "expression": ["greaterThanEq", "5E+2", 400], + "expects": true +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThanEq/sci-string-zero.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThanEq/sci-string-zero.json new file mode 100644 index 0000000000..bf5991b066 --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/greaterThanEq/sci-string-zero.json @@ -0,0 +1,5 @@ +{ + "name": "Should parse string scientific notation equivalent to 0 (false)", + "expression": ["greaterThanEq", "0e0", 10], + "expects": false +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThan/error-sci-not-string-format-1.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThan/error-sci-not-string-format-1.json new file mode 100644 index 0000000000..0647e9ff74 --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThan/error-sci-not-string-format-1.json @@ -0,0 +1,5 @@ +{ + "name": "Should throw exception when string scientific notation has plus sign before the E", + "expression": ["lessThan", "5+E2", 10], + "expectsFailure": "Expected number, got value \"5+E2\"" +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThan/error-sci-not-string-format-2.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThan/error-sci-not-string-format-2.json new file mode 100644 index 0000000000..1a1c549844 --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThan/error-sci-not-string-format-2.json @@ -0,0 +1,5 @@ +{ + "name": "Should throw exception when string scientific notation has negative sign before the E", + "expression": ["lessThan", "5-E2", 10], + "expectsFailure": "Expected number, got value \"5-E2\"" +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThan/error-sci-not-string-no-coefficient.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThan/error-sci-not-string-no-coefficient.json new file mode 100644 index 0000000000..409843188c --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThan/error-sci-not-string-no-coefficient.json @@ -0,0 +1,5 @@ +{ + "name": "Should throw exception when string scientific notation is missing the coefficient", + "expression": ["lessThan", "e2", 10], + "expectsFailure": "Expected number, got value \"e2\"" +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThan/error-sci-not-string-no-exponent.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThan/error-sci-not-string-no-exponent.json new file mode 100644 index 0000000000..1eab41ccc0 --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThan/error-sci-not-string-no-exponent.json @@ -0,0 +1,5 @@ +{ + "name": "Should throw exception when string scientific notation is missing the exponent", + "expression": ["lessThan", "5e", 10], + "expectsFailure": "Expected number, got value \"5e\"" +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThan/sci-notation-negative-exponents.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThan/sci-notation-negative-exponents.json new file mode 100644 index 0000000000..1ed8380157 --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThan/sci-notation-negative-exponents.json @@ -0,0 +1,5 @@ +{ + "name": "Should work with numbers with negative exponents (true)", + "expression": ["lessThan", 2e-3, 5e-3], + "expects": true +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThan/sci-notation-numbers.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThan/sci-notation-numbers.json new file mode 100644 index 0000000000..26d1bf9339 --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThan/sci-notation-numbers.json @@ -0,0 +1,5 @@ +{ + "name": "Should work with numbers in scientific notation (true)", + "expression": ["lessThan", 2e3, 5e3], + "expects": true +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThan/sci-notation-with-regular.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThan/sci-notation-with-regular.json new file mode 100644 index 0000000000..077b145579 --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThan/sci-notation-with-regular.json @@ -0,0 +1,5 @@ +{ + "name": "Should work with scientific notation and regular number (true)", + "expression": ["lessThan", 50, 1e2], + "expects": true +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThan/sci-string-basic.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThan/sci-string-basic.json new file mode 100644 index 0000000000..9d9a5c72f3 --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThan/sci-string-basic.json @@ -0,0 +1,5 @@ +{ + "name": "Should parse string scientific notation (true)", + "expression": ["lessThan", "5E2", 600], + "expects": true +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThan/sci-string-negative-coefficient.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThan/sci-string-negative-coefficient.json new file mode 100644 index 0000000000..5e89f35881 --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThan/sci-string-negative-coefficient.json @@ -0,0 +1,5 @@ +{ + "name": "Should parse string scientific notation with negative sign in front of coefficient (true)", + "expression": ["lessThan", "-5E2", 10], + "expects": true +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThan/sci-string-negative-exponent.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThan/sci-string-negative-exponent.json new file mode 100644 index 0000000000..9ef03f48e8 --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThan/sci-string-negative-exponent.json @@ -0,0 +1,5 @@ +{ + "name": "Should parse string scientific notation with negative sign in front of exponent (true)", + "expression": ["lessThan", "5e-2", 10], + "expects": true +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThan/sci-string-no-whole.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThan/sci-string-no-whole.json new file mode 100644 index 0000000000..15e6cd76cb --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThan/sci-string-no-whole.json @@ -0,0 +1,5 @@ +{ + "name": "Should parse string scientific notation with no whole number part (true)", + "expression": ["lessThan", ".5e2", 100], + "expects": true +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThan/sci-string-plus-coefficient.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThan/sci-string-plus-coefficient.json new file mode 100644 index 0000000000..ae75133ddc --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThan/sci-string-plus-coefficient.json @@ -0,0 +1,5 @@ +{ + "name": "Should parse string scientific notation with plus sign in front of coefficient (true)", + "expression": ["lessThan", "+5E2", 600], + "expects": true +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThan/sci-string-plus-exponent.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThan/sci-string-plus-exponent.json new file mode 100644 index 0000000000..46bec4df22 --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThan/sci-string-plus-exponent.json @@ -0,0 +1,5 @@ +{ + "name": "Should parse string scientific notation with plus sign in front of exponent (true)", + "expression": ["lessThan", "5E+2", 600], + "expects": true +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThan/sci-string-zero.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThan/sci-string-zero.json new file mode 100644 index 0000000000..b6ee01427d --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThan/sci-string-zero.json @@ -0,0 +1,5 @@ +{ + "name": "Should parse string scientific notation equivalent to 0 (true)", + "expression": ["lessThan", "0e0", 10], + "expects": true +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThanEq/error-sci-not-string-format-1.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThanEq/error-sci-not-string-format-1.json new file mode 100644 index 0000000000..2712cfe4ff --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThanEq/error-sci-not-string-format-1.json @@ -0,0 +1,5 @@ +{ + "name": "Should throw exception when string scientific notation has plus sign before the E", + "expression": ["lessThanEq", "5+E2", 10], + "expectsFailure": "Expected number, got value \"5+E2\"" +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThanEq/error-sci-not-string-format-2.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThanEq/error-sci-not-string-format-2.json new file mode 100644 index 0000000000..155956cbf4 --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThanEq/error-sci-not-string-format-2.json @@ -0,0 +1,5 @@ +{ + "name": "Should throw exception when string scientific notation has negative sign before the E", + "expression": ["lessThanEq", "5-E2", 10], + "expectsFailure": "Expected number, got value \"5-E2\"" +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThanEq/error-sci-not-string-no-coefficient.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThanEq/error-sci-not-string-no-coefficient.json new file mode 100644 index 0000000000..f9b729e7c8 --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThanEq/error-sci-not-string-no-coefficient.json @@ -0,0 +1,5 @@ +{ + "name": "Should throw exception when string scientific notation is missing the coefficient", + "expression": ["lessThanEq", "e2", 10], + "expectsFailure": "Expected number, got value \"e2\"" +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThanEq/error-sci-not-string-no-exponent.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThanEq/error-sci-not-string-no-exponent.json new file mode 100644 index 0000000000..7248e7ff6e --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThanEq/error-sci-not-string-no-exponent.json @@ -0,0 +1,5 @@ +{ + "name": "Should throw exception when string scientific notation is missing the exponent", + "expression": ["lessThanEq", "5e", 10], + "expectsFailure": "Expected number, got value \"5e\"" +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThanEq/sci-notation-negative-exponents.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThanEq/sci-notation-negative-exponents.json new file mode 100644 index 0000000000..493da61a9e --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThanEq/sci-notation-negative-exponents.json @@ -0,0 +1,5 @@ +{ + "name": "Should work with numbers with negative exponents (true)", + "expression": ["lessThanEq", 2e-3, 5e-3], + "expects": true +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThanEq/sci-notation-numbers.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThanEq/sci-notation-numbers.json new file mode 100644 index 0000000000..826aea1351 --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThanEq/sci-notation-numbers.json @@ -0,0 +1,5 @@ +{ + "name": "Should work with numbers in scientific notation (true)", + "expression": ["lessThanEq", 2e3, 5e3], + "expects": true +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThanEq/sci-notation-with-regular.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThanEq/sci-notation-with-regular.json new file mode 100644 index 0000000000..f57fe216f8 --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThanEq/sci-notation-with-regular.json @@ -0,0 +1,5 @@ +{ + "name": "Should work with scientific notation and regular number (true)", + "expression": ["lessThanEq", 50, 1e2], + "expects": true +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThanEq/sci-string-basic.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThanEq/sci-string-basic.json new file mode 100644 index 0000000000..3b48ddfc78 --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThanEq/sci-string-basic.json @@ -0,0 +1,5 @@ +{ + "name": "Should parse string scientific notation (true)", + "expression": ["lessThanEq", "5E2", 600], + "expects": true +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThanEq/sci-string-negative-coefficient.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThanEq/sci-string-negative-coefficient.json new file mode 100644 index 0000000000..09201f515c --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThanEq/sci-string-negative-coefficient.json @@ -0,0 +1,5 @@ +{ + "name": "Should parse string scientific notation with negative sign in front of coefficient (true)", + "expression": ["lessThanEq", "-5E2", 10], + "expects": true +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThanEq/sci-string-negative-exponent.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThanEq/sci-string-negative-exponent.json new file mode 100644 index 0000000000..ca695b27a2 --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThanEq/sci-string-negative-exponent.json @@ -0,0 +1,5 @@ +{ + "name": "Should parse string scientific notation with negative sign in front of exponent (true)", + "expression": ["lessThanEq", "5e-2", 10], + "expects": true +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThanEq/sci-string-no-whole.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThanEq/sci-string-no-whole.json new file mode 100644 index 0000000000..610176633d --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThanEq/sci-string-no-whole.json @@ -0,0 +1,5 @@ +{ + "name": "Should parse string scientific notation with no whole number part (true)", + "expression": ["lessThanEq", ".5e2", 100], + "expects": true +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThanEq/sci-string-plus-coefficient.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThanEq/sci-string-plus-coefficient.json new file mode 100644 index 0000000000..8e02dacce0 --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThanEq/sci-string-plus-coefficient.json @@ -0,0 +1,5 @@ +{ + "name": "Should parse string scientific notation with plus sign in front of coefficient (true)", + "expression": ["lessThanEq", "+5E2", 600], + "expects": true +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThanEq/sci-string-plus-exponent.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThanEq/sci-string-plus-exponent.json new file mode 100644 index 0000000000..6ac3916e55 --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThanEq/sci-string-plus-exponent.json @@ -0,0 +1,5 @@ +{ + "name": "Should parse string scientific notation with plus sign in front of exponent (true)", + "expression": ["lessThanEq", "5E+2", 600], + "expects": true +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThanEq/sci-string-zero.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThanEq/sci-string-zero.json new file mode 100644 index 0000000000..7c0f1aed32 --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/lessThanEq/sci-string-zero.json @@ -0,0 +1,5 @@ +{ + "name": "Should parse string scientific notation equivalent to 0 (true)", + "expression": ["lessThanEq", "0e0", 10], + "expects": true +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/minus/minus.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/minus/minus.json new file mode 100644 index 0000000000..dbc444c026 --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/minus/minus.json @@ -0,0 +1,180 @@ +{ + "name": "Minus tests", + "testCases": [ + { + "name": "Should subtract the second argument from the first", + "expression": ["minus", 0.1, 0.2], + "expects": -0.1 + }, + { + "name": "Should subtract the second negative argument from the first", + "expression": ["minus", -0.1, -0.2], + "expects": 0.1 + }, + { + "name": "Should return null when both of the arguments are null", + "expression": ["minus", null, null], + "expects": null + }, + { + "name": "Should return null when one of the arguments is null [null, decimal]", + "expression": ["minus", null, 2.1], + "expects": null + }, + { + "name": "Should return null when one of the arguments is null [decimal, null]", + "expression": ["minus", 2.1, null], + "expects": null + }, + { + "name": "Should subtract one integer from another", + "expression": ["minus", 50, 20], + "expects": 30 + }, + { + "name": "Should subtract [float, integer]", + "expression": ["minus", 50.5, 20], + "expects": 30.5 + }, + { + "name": "Should subtract [string, integer] when string is valid number", + "expression": ["minus", "50", 20], + "expects": 30 + }, + { + "name": "Should subtract [string, float] when string is valid number", + "expression": ["minus", "50.8", 20.3], + "expects": 30.5 + }, + { + "name": "Returns expected value for inputs that would return different result when treated as 64-bit binary floats", + "expression": ["minus", 50.8, 20.3], + "expects": 30.5 + }, + { + "name": "Should handle subtracting zero", + "expression": ["minus", 42, 0], + "expects": 42 + }, + { + "name": "Should handle subtracting from zero", + "expression": ["minus", 0, 42], + "expects": -42 + }, + { + "name": "Should subtract negative from positive", + "expression": ["minus", 50, -30], + "expects": 80 + }, + { + "name": "Should subtract numbers in scientific notation", + "expression": ["minus", 5e3, 2e3], + "expects": 3000 + }, + { + "name": "Should subtract numbers with negative exponents", + "expression": ["minus", 5e-3, 2e-3], + "expects": 0.003 + }, + { + "name": "Should subtract scientific notation from regular number", + "expression": ["minus", 150, 1e2], + "expects": 50 + }, + { + "name": "Should fail with invalid string that cannot be parsed as number", + "expression": ["minus", 50, "not a number"], + "expectsFailure": "Expected number, got value \"not a number\"" + }, + { + "name": "Should fail with [boolean, integer]", + "expression": ["minus", false, 10], + "expectsFailure": "Expected number, got value false" + }, + { + "name": "Should fail with string with no decimals after dot", + "expression": ["minus", "55.", 10], + "expectsFailure": "Expected number, got value \"55.\"" + }, + { + "name": "Should handle very large number formatted as string", + "expression": ["minus", 1, "900719925474099"], + "expects": -900719925474098 + }, + { + "name": "Should handle very small numbers", + "expression": ["minus", 0.0000003, 0.0000001], + "expects": 0.0000002 + }, + { + "name": "Should throw exception when less than two arguments are provided", + "expression": ["minus", 0.2], + "expectsFailure": "Invalid" + }, + { + "name": "Should parse string scientific notation with plus sign in front of coefficient", + "expression": ["minus", "+5E2", 10], + "expects": 490 + }, + { + "name": "Should parse string scientific notation with plus sign in front of exponent", + "expression": ["minus", "5E+2", 10], + "expects": 490 + }, + { + "name": "Should parse string scientific notation with negative sign in front of coefficient", + "expression": ["minus", "-5E2", 10], + "expects": -510 + }, + { + "name": "Should parse string scientific notation with negative sign in front of exponent", + "expression": ["minus", "5e-2", 10], + "expects": -9.95 + }, + { + "name": "Should subtract string scientific notation by number", + "expression": ["minus", "5E2", 10], + "expects": 490 + }, + { + "name": "Should subtract string scientific notation with no whole number part by number", + "expression": ["minus", ".5e2", 10], + "expects": 40 + }, + { + "name": "Should subtract string scientific notation equivalent to 0 by number", + "expression": ["minus", "0e0", 10], + "expects": -10 + }, + { + "name": "Should throw exception when string scientific notation has negative sign before the E", + "expression": ["minus", "5-E2", 10], + "expectsFailure": "Expected number, got value \"5-E2\"" + }, + { + "name": "Should throw exception when string scientific notation has plus sign before the E", + "expression": ["minus", "5+E2", 10], + "expectsFailure": "Expected number, got value \"5+E2\"" + }, + { + "name": "Should throw exception when string scientific notation is missing the exponent", + "expression": ["minus", "5e", 10], + "expectsFailure": "Expected number, got value \"5e\"" + }, + { + "name": "Should throw exception when string scientific notation is missing the coefficient", + "expression": ["minus", "e2", 10], + "expectsFailure": "Expected number, got value \"e2\"" + }, + { + "name": "Should throw exception when more than two arguments are present", + "expression": ["minus", 0.1, 0.2, 15, 1.50], + "expectsFailure": "Invalid" + }, + { + "name": "Should subtract negative from positive decimal", + "expression": ["minus", 50.55, -30.77], + "expects": 81.32 + } + ] +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/multiply/multiply.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/multiply/multiply.json new file mode 100644 index 0000000000..2e23d10a39 --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/multiply/multiply.json @@ -0,0 +1,185 @@ +{ + "name": "Multiply tests", + "testCases": [ + { + "name": "Should multiply the two arguments", + "expression": ["multiply", 0.1, 0.2], + "expects": 0.02 + }, + { + "name": "Returns expected value for inputs that would return different result when treated as 64-bit binary floats", + "expression": ["multiply", 0.1, 0.2], + "expects": 0.02 + }, + { + "name": "Should return null when both of the arguments are null", + "expression": ["multiply", null, null], + "expects": null + }, + { + "name": "Should multiply the two negative arguments", + "expression": ["multiply", -0.1, -0.2], + "expects": 0.02 + }, + { + "name": "Should return null when one of the arguments is null [null, decimal]", + "expression": ["multiply", null, 2.1], + "expects": null + }, + { + "name": "Should return null when one of the arguments is null [decimal, null]", + "expression": ["multiply", 2.1, null], + "expects": null + }, + { + "name": "Should multiply two integers", + "expression": ["multiply", 5, 6], + "expects": 30 + }, + { + "name": "Should multiply [float, integer]", + "expression": ["multiply", 7.5, 4], + "expects": 30.0 + }, + { + "name": "Should multiply [string, integer] when string is valid number", + "expression": ["multiply", "5", 6], + "expects": 30 + }, + { + "name": "Should multiply [string, float] when string is valid number", + "expression": ["multiply", "5.5", 4.0], + "expects": 22.0 + }, + { + "name": "Should handle multiplying by zero", + "expression": ["multiply", 42, 0], + "expects": 0 + }, + { + "name": "Should multiply negative and positive numbers", + "expression": ["multiply", -5, 6], + "expects": -30 + }, + { + "name": "Should multiply two negative numbers", + "expression": ["multiply", -5, -6], + "expects": 30 + }, + { + "name": "Should multiply numbers in scientific notation", + "expression": ["multiply", 2e3, 3e2], + "expects": 600000 + }, + { + "name": "Should multiply numbers with negative exponents", + "expression": ["multiply", 2e-3, 3e-2], + "expects": 0.00006 + }, + { + "name": "Should multiply scientific notation with regular number", + "expression": ["multiply", 1e2, 5], + "expects": 500 + }, + { + "name": "Should fail with invalid string that cannot be parsed as number", + "expression": ["multiply", "not a number", 5], + "expectsFailure": "Expected number, got value \"not a number\"" + }, + { + "name": "Should fail with [boolean, integer]", + "expression": ["multiply", true, 5], + "expectsFailure": "Expected number, got value true" + }, + { + "name": "Should fail with string with no decimals after dot", + "expression": ["multiply", "55.", 5], + "expectsFailure": "Expected number, got value \"55.\"" + }, + { + "name": "Should handle very large numbers within the safe range", + "expression": ["multiply", 1000000, 1000000], + "expects": 1000000000000 + }, + { + "name": "Should handle very large number formatted as string", + "expression": ["multiply", 1, "900719925474099"], + "expects": 900719925474099 + }, + { + "name": "Should handle very small numbers", + "expression": ["multiply", 0.0001, 0.0001], + "expects": 0.00000001 + }, + { + "name": "Should multiply string scientific notation with plus sign in front of coefficient", + "expression": ["multiply", "+5E2", 10], + "expects": 5000 + }, + { + "name": "Should multiply string scientific notation with plus sign in front of exponent", + "expression": ["multiply", "5E+2", 10], + "expects": 5000 + }, + { + "name": "Should multiply string scientific notation with negative sign in front of coefficient", + "expression": ["multiply", "-5E2", 10], + "expects": -5000 + }, + { + "name": "Should multiply string scientific notation with negative sign in front of exponent", + "expression": ["multiply", "5e-2", 10], + "expects": 0.5 + }, + { + "name": "Should multiply string scientific notation by number", + "expression": ["multiply", "5E2", 10], + "expects": 5000 + }, + { + "name": "Should multiply string scientific notation with no whole number part by number", + "expression": ["multiply", ".5e2", 10], + "expects": 500 + }, + { + "name": "Should multiply string scientific notation equivalent to 0 by number", + "expression": ["multiply", "0e0", 10], + "expects": 0 + }, + { + "name": "Should throw exception when string scientific notation has negative sign before the E", + "expression": ["multiply", "5-E2", 10], + "expectsFailure": "Expected number, got value \"5-E2\"" + }, + { + "name": "Should throw exception when string scientific notation has plus sign before the E", + "expression": ["multiply", "5+E2", 10], + "expectsFailure": "Expected number, got value \"5+E2\"" + }, + { + "name": "Should throw exception when string scientific notation is missing the exponent", + "expression": ["multiply", "5e", 10], + "expectsFailure": "Expected number, got value \"5e\"" + }, + { + "name": "Should throw exception when string scientific notation is missing the coefficient", + "expression": ["multiply", "e2", 10], + "expectsFailure": "Expected number, got value \"e2\"" + }, + { + "name": "Should throw exception when less than two arguments are provided", + "expression": ["multiply", 0.1], + "expectsFailure": "Invalid" + }, + { + "name": "Should throw exception when more than two arguments are present", + "expression": ["multiply", 0.1, 0.2, 15, 1.50], + "expectsFailure": "Invalid" + }, + { + "name": "Should multiply negative and positive decimal numbers", + "expression": ["multiply", -5.55, 6.66], + "expects": -36.963 + } + ] +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/plus/plus.json b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/plus/plus.json new file mode 100644 index 0000000000..03140979c8 --- /dev/null +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/CommonTests/shared-tests/functions/plus/plus.json @@ -0,0 +1,170 @@ +{ + "name": "Plus tests", + "testCases": [ + { + "name": "Should add the two given numbers together", + "expression": ["plus", 0.1, 0.2], + "expects": 0.3 + }, + { + "name": "Returns expected value for inputs that would return different result when treated as 64-bit binary floats", + "expression": ["plus", 0.1, 0.2], + "expects": 0.3 + }, + { + "name": "Should add two negative numbers together", + "expression": ["plus", -4, -0.2], + "expects": -4.2 + }, + { + "name": "Should return null when both of the arguments are null", + "expression": ["plus", null, null], + "expects": null + }, + { + "name": "Should return null when one of the arguments is null [decimal, null]", + "expression": ["plus", 4.3, null], + "expects": null + }, + { + "name": "Should return null when one of the arguments is null [null, decimal]", + "expression": ["plus", null, 4.3], + "expects": null + }, + { + "name": "Should add two integers", + "expression": ["plus", 10, 20], + "expects": 30 + }, + { + "name": "Should add [float, integer]", + "expression": ["plus", 10.5, 20], + "expects": 30.5 + }, + { + "name": "Should add [string, integer] when string is valid number", + "expression": ["plus", "10", 20], + "expects": 30 + }, + { + "name": "Should add [string, float] when string is valid number", + "expression": ["plus", "10.5", 20.3], + "expects": 30.8 + }, + { + "name": "Should add negative and positive numbers", + "expression": ["plus", 50, -30], + "expects": 20 + }, + { + "name": "Should add numbers in scientific notation", + "expression": ["plus", 1e3, 2e3], + "expects": 3000 + }, + { + "name": "Should add numbers with negative exponents", + "expression": ["plus", 1e-3, 2e-3], + "expects": 0.003 + }, + { + "name": "Should add scientific notation with regular number", + "expression": ["plus", 1e2, 50], + "expects": 150 + }, + { + "name": "Should fail with invalid string that cannot be parsed as number", + "expression": ["plus", "not a number", 10], + "expectsFailure": "Expected number, got value \"not a number\"" + }, + { + "name": "Should fail with [boolean, integer]", + "expression": ["plus", true, 10], + "expectsFailure": "Expected number, got value true" + }, + { + "name": "Should fail with string with no decimals after dot", + "expression": ["plus", "55.", 10], + "expectsFailure": "Expected number, got value \"55.\"" + }, + { + "name": "Should handle very large number formatted as string", + "expression": ["plus", 1, "900719925474099"], + "expects": 900719925474100 + }, + { + "name": "Should handle very small numbers", + "expression": ["plus", 0.0000001, 0.0000002], + "expects": 0.0000003 + }, + { + "name": "Should add string scientific notation with plus sign in front of coefficient to number", + "expression": ["plus", "+5E2", 10], + "expects": 510 + }, + { + "name": "Should add string scientific notation with plus sign in front of exponent to number", + "expression": ["plus", "5E+2", 10], + "expects": 510 + }, + { + "name": "Should add string scientific notation with negative sign in front of coefficient to number", + "expression": ["plus", "-5E2", 10], + "expects": -490 + }, + { + "name": "Should add string scientific notation with negative sign in front of exponent to number", + "expression": ["plus", "5e-2", 10], + "expects": 10.05 + }, + { + "name": "Should add string scientific notation to number", + "expression": ["plus", "5E2", 10], + "expects": 510 + }, + { + "name": "Should add string scientific notation with no whole number part to number", + "expression": ["plus", ".5e2", 10], + "expects": 60 + }, + { + "name": "Should add string scientific notation equivalent to 0 to number", + "expression": ["plus", "0e0", 10], + "expects": 10 + }, + { + "name": "Should throw exception when string scientific notation has negative sign before the E", + "expression": ["plus", "5-E2", 10], + "expectsFailure": "Expected number, got value \"5-E2\"" + }, + { + "name": "Should throw exception when string scientific notation has plus sign before the E", + "expression": ["plus", "5+E2", 10], + "expectsFailure": "Expected number, got value \"5+E2\"" + }, + { + "name": "Should throw exception when string scientific notation is missing the exponent", + "expression": ["plus", "5e", 10], + "expectsFailure": "Expected number, got value \"5e\"" + }, + { + "name": "Should throw exception when string scientific notation is missing the coefficient", + "expression": ["plus", "e2", 10], + "expectsFailure": "Expected number, got value \"e2\"" + }, + { + "name": "Should throw exception when less than two arguments are provided", + "expression": ["plus", 0.2], + "expectsFailure": "Invalid" + }, + { + "name": "Should throw exception when more than two arguments are present", + "expression": ["plus", 0.1, 0.2, 15, 1.50], + "expectsFailure": "Invalid" + }, + { + "name": "Should add negative and positive decimal numbers", + "expression": ["plus", 50.55, -30.66], + "expects": 19.89 + } + ] +} diff --git a/test/Altinn.App.Core.Tests/LayoutExpressions/ExpressionEvaluatorTests/EqualsTests.cs b/test/Altinn.App.Core.Tests/LayoutExpressions/ExpressionEvaluatorTests/EqualsTests.cs index b34947d406..938eb0373d 100644 --- a/test/Altinn.App.Core.Tests/LayoutExpressions/ExpressionEvaluatorTests/EqualsTests.cs +++ b/test/Altinn.App.Core.Tests/LayoutExpressions/ExpressionEvaluatorTests/EqualsTests.cs @@ -50,10 +50,10 @@ public static TheoryData GetNumericTestData(double value) DateTimeOffset.Parse("2025-02-04T13:13:15.84473533+01:00"), DateOnly.FromDateTime(DateTime.Parse("2025-02-04T13:13:15.8447353+01:00")), TimeOnly.FromDateTime(DateTime.Parse("2025-02-04T13:13:15.8447353+01:00")), - ((long)int.MaxValue) + 1, - ((ulong)uint.MaxValue) + 1, - ((decimal)int.MaxValue) + 1, - ((decimal)uint.MaxValue) + 1, + (long)int.MaxValue + 1, + (ulong)uint.MaxValue + 1, + (decimal)int.MaxValue + 1, + (decimal)uint.MaxValue + 1, (double)((decimal)long.MaxValue + 1), (double)((decimal)ulong.MaxValue + 1), }; diff --git a/test/Altinn.App.Core.Tests/PublicApiTests.PublicApi_ShouldNotChange_Unintentionally.verified.txt b/test/Altinn.App.Core.Tests/PublicApiTests.PublicApi_ShouldNotChange_Unintentionally.verified.txt index 2fbe64b0bf..de588825a1 100644 --- a/test/Altinn.App.Core.Tests/PublicApiTests.PublicApi_ShouldNotChange_Unintentionally.verified.txt +++ b/test/Altinn.App.Core.Tests/PublicApiTests.PublicApi_ShouldNotChange_Unintentionally.verified.txt @@ -4583,6 +4583,10 @@ namespace Altinn.App.Core.Models.Expressions gatewayAction = 34, language = 35, text = 36, + plus = 37, + minus = 38, + multiply = 39, + divide = 40, } } namespace Altinn.App.Core.Models.Layout.Components.Base diff --git a/test/Altinn.App.Core.Tests/TestUtils/FileNamesInFolderAttribute.cs b/test/Altinn.App.Core.Tests/TestUtils/FileNamesInFolderAttribute.cs index d7009ccab8..cb1ff3166f 100644 --- a/test/Altinn.App.Core.Tests/TestUtils/FileNamesInFolderAttribute.cs +++ b/test/Altinn.App.Core.Tests/TestUtils/FileNamesInFolderAttribute.cs @@ -1,5 +1,4 @@ using System.Reflection; -using System.Runtime.CompilerServices; using Xunit.Sdk; namespace Altinn.App.Core.Tests.TestUtils; @@ -11,7 +10,7 @@ public FileNamesInFolderDataAttribute(string[] folderParts) public override IEnumerable GetData(MethodInfo testMethod) { - var basePath = AltinnAppTestsBasePath(); + var basePath = TestAttributeHelper.AltinnAppTestsBasePath(); var folder = Path.Join(basePath, folderName); if (!Directory.Exists(folder)) { @@ -27,24 +26,4 @@ public override IEnumerable GetData(MethodInfo testMethod) } ); } - - private static string AltinnAppTestsBasePath([CallerFilePath] string? callerFilePath = null) - { - if (callerFilePath is null) - { - throw new Exception("Caller path is null"); - } - var testUtilsDirectoryPath = Path.GetDirectoryName(callerFilePath); - if (testUtilsDirectoryPath is null) - { - throw new Exception("Caller path is null"); - } - var callerDirectoryPath = Path.GetDirectoryName(testUtilsDirectoryPath); - if (callerDirectoryPath is null) - { - throw new Exception("Caller path is null"); - } - - return callerDirectoryPath; - } } diff --git a/test/Altinn.App.Core.Tests/TestUtils/TestAttributeHelper.cs b/test/Altinn.App.Core.Tests/TestUtils/TestAttributeHelper.cs new file mode 100644 index 0000000000..5f33676fc1 --- /dev/null +++ b/test/Altinn.App.Core.Tests/TestUtils/TestAttributeHelper.cs @@ -0,0 +1,26 @@ +using System.Runtime.CompilerServices; + +namespace Altinn.App.Core.Tests.TestUtils; + +public static class TestAttributeHelper +{ + public static string AltinnAppTestsBasePath([CallerFilePath] string? callerFilePath = null) + { + if (callerFilePath is null) + { + throw new InvalidOperationException("CallerFilePath attribute returned null"); + } + var testUtilsDirectoryPath = Path.GetDirectoryName(callerFilePath); + if (testUtilsDirectoryPath is null) + { + throw new InvalidOperationException($"Could not get directory name from caller path: {callerFilePath}"); + } + var callerDirectoryPath = Path.GetDirectoryName(testUtilsDirectoryPath); + if (callerDirectoryPath is null) + { + throw new InvalidOperationException($"Could not get parent directory from: {testUtilsDirectoryPath}"); + } + + return callerDirectoryPath; + } +} diff --git a/test/Altinn.App.Core.Tests/TestUtils/TestCasesAttribute.cs b/test/Altinn.App.Core.Tests/TestUtils/TestCasesAttribute.cs new file mode 100644 index 0000000000..0c6ca78293 --- /dev/null +++ b/test/Altinn.App.Core.Tests/TestUtils/TestCasesAttribute.cs @@ -0,0 +1,38 @@ +using System.Reflection; +using System.Text.Json; +using Altinn.App.Core.Tests.LayoutExpressions.CommonTests; +using Xunit.Sdk; + +namespace Altinn.App.Core.Tests.TestUtils; + +public class TestCasesAttribute(string folderName) : DataAttribute +{ + private static readonly JsonSerializerOptions _jsonSerializerOptions = new() + { + ReadCommentHandling = JsonCommentHandling.Skip, + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + }; + + public override IEnumerable GetData(MethodInfo testMethod) + { + var basePath = TestAttributeHelper.AltinnAppTestsBasePath(); + var folder = Path.Join(basePath, folderName); + if (!Directory.Exists(folder)) + { + throw new DirectoryNotFoundException($"Folder not found: {folder}"); + } + var files = Directory.GetFiles(folder, "*.json"); + var theoryData = new List(); + foreach (var file in files) + { + var data = File.ReadAllText(file); + var rootCases = JsonSerializer.Deserialize(data, _jsonSerializerOptions); + if (rootCases?.TestCases is not null) + { + theoryData.AddRange(rootCases.TestCases); + } + } + + return theoryData.Select(x => new object[] { x.Name ?? string.Empty, x }); + } +}