using w4c_workflows.Models.Nodes; using w4c_workflows.Services.Nodes; using Xunit; namespace w4c_workflows.Tests; public class NodeBlueprintCatalogTests { private static NodeBlueprint Blueprint(string type, double version, string display, string kind = NodeKind.Action, params string[] categories) => new() { Type = type, Version = version, DisplayName = display, Kind = kind, Categories = categories.ToList(), }; [Fact] public void LoadEmbedded_finds_the_core_blueprints() { var catalog = new NodeBlueprintCatalog(NodeBlueprintCatalog.LoadEmbedded()); Assert.True(catalog.Contains("core.noop")); Assert.True(catalog.Contains("core.set")); Assert.True(catalog.Contains("core.if")); Assert.True(catalog.Contains("core.httpRequest")); } [Fact] public void Core_blueprints_expose_expected_ports() { var catalog = new NodeBlueprintCatalog(NodeBlueprintCatalog.LoadEmbedded()); var branch = catalog.Get("core.if"); Assert.NotNull(branch); Assert.Equal(2, branch!.Outputs.Count); Assert.Equal("true", branch.Outputs[0].Label); Assert.Equal("false", branch.Outputs[1].Label); var request = catalog.Get("core.httpRequest"); Assert.NotNull(request); Assert.True(request!.ProducesErrorBranch); } [Fact] public void Resolve_without_version_returns_the_highest() { var catalog = new NodeBlueprintCatalog(new[] { Blueprint("demo", 1, "Demo v1"), Blueprint("demo", 2, "Demo v2"), Blueprint("demo", 2.5, "Demo v2.5"), }); Assert.Equal(2.5, catalog.Resolve("demo")!.Version); } [Fact] public void Resolve_picks_the_closest_version_not_newer_than_requested() { var catalog = new NodeBlueprintCatalog(new[] { Blueprint("demo", 1, "Demo v1"), Blueprint("demo", 2, "Demo v2"), Blueprint("demo", 2.5, "Demo v2.5"), }); Assert.Equal(2, catalog.Resolve("demo", 2.2)!.Version); Assert.Equal(1, catalog.Resolve("demo", 1.9)!.Version); Assert.Equal(2, catalog.Resolve("demo", 2)!.Version); Assert.Null(catalog.Resolve("demo", 0.5)); } [Fact] public void Duplicate_type_and_version_is_rejected() { var catalog = new NodeBlueprintCatalog(new[] { Blueprint("demo", 1, "A") }); Assert.Throws(() => new NodeBlueprintCatalog(new[] { Blueprint("demo", 1, "A"), Blueprint("demo", 1, "B") })); } [Fact] public void Search_filters_by_query_kind_and_category() { var catalog = new NodeBlueprintCatalog(new[] { Blueprint("slack.send", 1, "Send message", NodeKind.Action, "Communication"), Blueprint("if.branch", 1, "If", NodeKind.Control, "Flow"), }); Assert.Single(catalog.Search(query: "slack")); Assert.Single(catalog.Search(kind: NodeKind.Control)); Assert.Single(catalog.Search(category: "Communication")); Assert.Empty(catalog.Search(query: "does-not-exist")); } [Fact] public void Categories_are_distinct_and_sorted() { var catalog = new NodeBlueprintCatalog(new[] { Blueprint("a", 1, "A", NodeKind.Action, "Zeta"), Blueprint("b", 1, "B", NodeKind.Action, "Alpha", "Zeta"), }); Assert.Equal(new[] { "Alpha", "Zeta" }, catalog.Categories); } [Fact] public void HasParameter_searches_nested_collection_fields() { var catalog = new NodeBlueprintCatalog(NodeBlueprintCatalog.LoadEmbedded()); var set = catalog.Get("core.set")!; Assert.True(set.HasParameter("mode")); Assert.True(set.HasParameter("name")); // nested inside the fixedCollection Assert.False(set.HasParameter("nope")); } }