using Godosa.Core.Runs.Scripts; using Xunit; namespace Godosa.Core.Tests.Runs.Scripts; public class ConditionTests { private sealed class Ctx : IConditionContext { public Dictionary Values { get; } = new() { ["quest(1)"] = RunValue.Of(2), ["map"] = RunValue.Of("tarant"), ["dialog-open"] = RunValue.Of(true), ["global(gold)"] = RunValue.Of(500), ["alive"] = RunValue.Of(false), }; public bool HasProbe(string name) => name is "quest" or "map" or "dialog-open" or "global" or "alive"; public RunValue Probe(string name, IReadOnlyList args) => Values[args.Count == 0 ? name : $"{name}({string.Join(",", args)})"]; public long? Constant(string name) => name switch { "accepted" => 2, "completed" => 4, _ => null }; } private static bool Test(string text) => ConditionParser.Parse(text).Test(new Ctx()); [Theory] [InlineData("quest(1) >= accepted", true)] [InlineData("quest(1) = completed", false)] [InlineData("map = \"tarant\"", true)] [InlineData("map != \"ashbury\"", true)] [InlineData("dialog-open", true)] [InlineData("alive", false)] [InlineData("not alive", true)] [InlineData("dialog-open and global(gold) > 499", true)] [InlineData("alive or global(gold) < 100", false)] [InlineData("not (alive or dialog-open)", false)] [InlineData("alive or dialog-open and quest(1) = 2", true)] // and binds tighter than or [InlineData("global(gold) <= 500", true)] public void Evaluates(string text, bool expected) => Assert.Equal(expected, Test(text)); [Fact] public void MismatchedTypes_Fault() => Assert.Equal("cannot compare tarant with 3", Assert.Throws(() => Test("map > 3")).Message); [Theory] [InlineData("quest(1) >=")] [InlineData("(alive")] [InlineData("alive alive")] [InlineData("\"open")] public void BadSyntax_Throws(string text) => Assert.Throws(() => ConditionParser.Parse(text)); [Fact] public void ListsProbesAndBareNames() { var c = ConditionParser.Parse("quest(1) >= accepted and not dialog-open"); Assert.Equal(["quest(1)", "accepted", "dialog-open"], c.Probes().Select(p => p.Args.Count == 0 ? p.Name : $"{p.Name}({string.Join(",", p.Args)})")); Assert.Equal(["accepted", "dialog-open"], c.Bare()); } [Fact] public void Describe_ListsProbeValues() => Assert.Equal("quest(1)=2 map=tarant", Cond.Describe(ConditionParser.Parse("quest(1) > 3 and map = \"x\""), new Ctx())); }