w4c-workflows-api/w4c-workflows-api.Tests/NodeBlueprintCatalogTests.cs
2026-09-11 19:04:50 +03:00

122 lines
3.9 KiB
C#

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<InvalidOperationException>(() =>
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"));
}
}