diff --git a/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleEventFormatter.cs b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleEventFormatter.cs index 8072104615..1d1922df01 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleEventFormatter.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleEventFormatter.cs @@ -47,6 +47,7 @@ public RuleEventFormatter(IJsonSerializer jsonSerializer, IRuleUrlGenerator urlG AddPattern("APP_ID", AppId); AddPattern("APP_NAME", AppName); AddPattern("CONTENT_ACTION", ContentAction); + AddPattern("CONTENT_STATUS", ContentStatus); AddPattern("CONTENT_URL", ContentUrl); AddPattern("SCHEMA_ID", SchemaId); AddPattern("SCHEMA_NAME", SchemaName); @@ -212,6 +213,16 @@ private static string ContentAction(EnrichedEvent @event) return Fallback; } + private static string ContentStatus(EnrichedEvent @event) + { + if (@event is EnrichedContentEvent contentEvent) + { + return contentEvent.Status.ToString(); + } + + return Fallback; + } + private string ContentUrl(EnrichedEvent @event) { if (@event is EnrichedContentEvent contentEvent) diff --git a/src/Squidex.Domain.Apps.Core.Operations/Scripting/DefaultConverter.cs b/src/Squidex.Domain.Apps.Core.Operations/Scripting/DefaultConverter.cs index 5959acc302..4cd2a9007f 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/Scripting/DefaultConverter.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/Scripting/DefaultConverter.cs @@ -46,6 +46,9 @@ public bool TryConvert(Engine engine, object value, out JsValue result) case Instant instant: result = JsValue.FromObject(engine, instant.ToDateTimeUtc()); return true; + case Status status: + result = status.ToString(); + return true; case NamedContentData content: result = new ContentDataObject(engine, content); return true; diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleEventFormatterTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleEventFormatterTests.cs index 3e5712af7b..c88f5de4f0 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleEventFormatterTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleEventFormatterTests.cs @@ -170,6 +170,22 @@ public void Should_format_content_url_when_not_found(string script) Assert.Equal("Go to null", sut.Format(script, new EnrichedAssetEvent())); } + [Theory] + [InlineData("$CONTENT_STATUS")] + [InlineData("Script(`${event.status}`)")] + public void Should_format_content_status_when_found(string script) + { + Assert.Equal("Published", sut.Format(script, new EnrichedContentEvent { Status = Status.Published })); + } + + [Theory] + [InlineData("$CONTENT_ACTION")] + [InlineData("Script(contentAction())")] + public void Should_null_when_content_status_not_found(string script) + { + Assert.Equal("null", sut.Format(script, new EnrichedAssetEvent())); + } + [Theory] [InlineData("$CONTENT_ACTION")] [InlineData("Script(`${event.type}`)")] diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/Scripting/JintScriptEngineTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/Scripting/JintScriptEngineTests.cs index ac60cd8ffa..0d25ccfde4 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/Scripting/JintScriptEngineTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/Scripting/JintScriptEngineTests.cs @@ -17,38 +17,38 @@ namespace Squidex.Domain.Apps.Core.Operations.Scripting { public class JintScriptEngineTests { - private readonly JintScriptEngine scriptEngine = new JintScriptEngine { Timeout = TimeSpan.FromSeconds(1) }; + private readonly JintScriptEngine sut = new JintScriptEngine { Timeout = TimeSpan.FromSeconds(1) }; [Fact] public void Should_throw_validation_exception_when_calling_reject() { - Assert.Throws(() => scriptEngine.Execute(new ScriptContext(), "reject()")); - Assert.Throws(() => scriptEngine.Execute(new ScriptContext(), "reject('Not valid')")); + Assert.Throws(() => sut.Execute(new ScriptContext(), "reject()")); + Assert.Throws(() => sut.Execute(new ScriptContext(), "reject('Not valid')")); } [Fact] public void Should_throw_security_exception_when_calling_reject() { - Assert.Throws(() => scriptEngine.Execute(new ScriptContext(), "disallow()")); - Assert.Throws(() => scriptEngine.Execute(new ScriptContext(), "disallow('Not allowed')")); + Assert.Throws(() => sut.Execute(new ScriptContext(), "disallow()")); + Assert.Throws(() => sut.Execute(new ScriptContext(), "disallow('Not allowed')")); } [Fact] public void Should_catch_script_syntax_errors() { - Assert.Throws(() => scriptEngine.Execute(new ScriptContext(), "x => x")); + Assert.Throws(() => sut.Execute(new ScriptContext(), "x => x")); } [Fact] public void Should_catch_script_runtime_errors() { - Assert.Throws(() => scriptEngine.Execute(new ScriptContext(), "throw 'Error';")); + Assert.Throws(() => sut.Execute(new ScriptContext(), "throw 'Error';")); } [Fact] public void Should_catch_script_runtime_errors_on_execute_and_transform() { - Assert.Throws(() => scriptEngine.ExecuteAndTransform(new ScriptContext(), "throw 'Error';")); + Assert.Throws(() => sut.ExecuteAndTransform(new ScriptContext(), "throw 'Error';")); } [Fact] @@ -57,7 +57,7 @@ public void Should_return_original_content_when_transform_script_failed() var content = new NamedContentData(); var context = new ScriptContext { Data = content }; - var result = scriptEngine.Transform(context, "x => x"); + var result = sut.Transform(context, "x => x"); Assert.Same(content, result); } @@ -68,7 +68,7 @@ public void Should_throw_when_execute_and_transform_script_failed() var content = new NamedContentData(); var context = new ScriptContext { Data = content }; - Assert.Throws(() => scriptEngine.ExecuteAndTransform(context, "x => x")); + Assert.Throws(() => sut.ExecuteAndTransform(context, "x => x")); } [Fact] @@ -77,7 +77,7 @@ public void Should_return_original_content_when_content_is_not_replaced() var content = new NamedContentData(); var context = new ScriptContext { Data = content }; - var result = scriptEngine.ExecuteAndTransform(context, "var x = 0;"); + var result = sut.ExecuteAndTransform(context, "var x = 0;"); Assert.Same(content, result); } @@ -95,7 +95,7 @@ public void Should_fetch_operation_name() var context = new ScriptContext { Data = content, Operation = "MyOperation" }; - var result = scriptEngine.ExecuteAndTransform(context, @" + var result = sut.ExecuteAndTransform(context, @" var data = ctx.data; data.operation = { iv: ctx.operation }; @@ -127,7 +127,7 @@ public void Should_transform_content_and_return_with_transform() var context = new ScriptContext { Data = content }; - var result = scriptEngine.Transform(context, @" + var result = sut.Transform(context, @" var data = ctx.data; delete data.number0; @@ -160,7 +160,7 @@ public void Should_slugify_value() var context = new ScriptContext { Data = content }; - var result = scriptEngine.Transform(context, @" + var result = sut.Transform(context, @" var data = ctx.data; data.slug = { iv: slugify(data.title.iv) }; @@ -190,7 +190,7 @@ public void Should_slugify_value_with_single_char() var context = new ScriptContext { Data = content }; - var result = scriptEngine.Transform(context, @" + var result = sut.Transform(context, @" var data = ctx.data; data.slug = { iv: slugify(data.title.iv, true) }; @@ -222,7 +222,7 @@ public void Should_transform_content_and_return_with_execute_transform() var context = new ScriptContext { Data = content }; - var result = scriptEngine.ExecuteAndTransform(context, @" + var result = sut.ExecuteAndTransform(context, @" var data = ctx.data; delete data.number0; @@ -263,12 +263,44 @@ public void Should_transform_content_with_old_content() var context = new ScriptContext { Data = content, OldData = oldContent, User = userPrincipal }; - var result = scriptEngine.ExecuteAndTransform(context, @" + var result = sut.ExecuteAndTransform(context, @" ctx.data.number0.iv = ctx.data.number0.iv + ctx.oldData.number0.iv * parseInt(ctx.user.id, 10); replace(ctx.data);"); Assert.Equal(expected, result); } + + [Fact] + public void Should_evaluate_to_true_when_expression_match() + { + var result = sut.Evaluate("value", new { i = 2 }, "value.i == 2"); + + Assert.True(result); + } + + [Fact] + public void Should_evaluate_to_true_when_status_match() + { + var result = sut.Evaluate("value", new { status = Status.Published }, "value.status == 'Published'"); + + Assert.True(result); + } + + [Fact] + public void Should_evaluate_to_false_when_expression_match() + { + var result = sut.Evaluate("value", new { i = 2 }, "value.i == 3"); + + Assert.False(result); + } + + [Fact] + public void Should_evaluate_to_false_when_script_is_invalid() + { + var result = sut.Evaluate("value", new { i = 2 }, "function()"); + + Assert.False(result); + } } }