feat(api): DI-register 5 nodes + NATS provider; enable pending integration tests

This commit is contained in:
Claude
2026-08-28 15:35:43 +00:00
parent df64e9e512
commit 6065f0c91e
6 changed files with 50 additions and 6 deletions

View File

@@ -7,8 +7,10 @@ using VolcanicCore.Api.Registries;
using VolcanicCore.Core;
using VolcanicCore.Persistence;
using VolcanicCore.Persistence.Encryption;
using VolcanicCore.Nodes;
using VolcanicCore.Persistence.Migrations;
using VolcanicCore.Persistence.Repositories;
using VolcanicCore.Providers;
var builder = WebApplication.CreateBuilder(args);
@@ -120,6 +122,9 @@ builder.Services.AddSingleton<IConnectionInstanceRegistry>(sp =>
builder.Services.AddSingleton<WebhookRouter>();
builder.Services.AddSingleton<WebhookRegistry>();
builder.Services.AddVolcanicProviders();
builder.Services.AddVolcanicNodes();
builder.Services.AddSingleton<Executor>();
builder.Services.AddSingleton<TriggerHost>();
builder.Services.AddSingleton<IWorkflowLifecycle>(sp => sp.GetRequiredService<TriggerHost>());

View File

@@ -0,0 +1,17 @@
using Microsoft.Extensions.DependencyInjection;
using VolcanicCore.Core;
namespace VolcanicCore.Nodes;
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddVolcanicNodes(this IServiceCollection services)
{
services.AddSingleton<INodeType, NatsHookNode>();
services.AddSingleton<INodeType, NatsPublishNode>();
services.AddSingleton<INodeType, WebhookNode>();
services.AddSingleton<INodeType, WebResponseNode>();
services.AddSingleton<INodeType, PythonTransformNode>();
return services;
}
}

View File

@@ -72,5 +72,23 @@ public class ConnectionsEndpointsTests : IClassFixture<WebFactory>
Assert.Equal(HttpStatusCode.Conflict, second.StatusCode);
}
[Fact]
public async Task Nats_connection_response_never_returns_pass_field()
{
var c = await LoggedIn();
var create = await c.PostAsJsonAsync("/api/connections", new
{
providerId = "nats",
name = "nats-secret-test",
config = new { url = "nats://x", user = "u", pass = "shhh" }
});
Assert.Equal(HttpStatusCode.Created, create.StatusCode);
var created = await create.Content.ReadFromJsonAsync<JsonElement>();
var id = created.GetProperty("id").GetString()!;
var get = await c.GetFromJsonAsync<JsonElement>($"/api/connections/{id}");
Assert.DoesNotContain(get.GetProperty("config").EnumerateObject(), p => p.Name == "pass");
}
private sealed record ConnectionDto(string Id, string ProviderId, string Name, JsonElement Config);
}

View File

@@ -24,21 +24,25 @@ public class DiscoveryEndpointsTests : IClassFixture<WebFactory>
}
[Fact]
public async Task Node_types_returns_registered_types_empty_in_plan_1()
public async Task Node_types_returns_five_registered_types()
{
var c = await LoggedIn();
var res = await c.GetFromJsonAsync<List<NodeTypeDto>>("/api/node-types");
Assert.NotNull(res);
Assert.Empty(res!); // Plan 2 adds the 5 nodes.
var ids = res!.Select(n => n.Id).ToHashSet();
Assert.Subset(new HashSet<string>
{
"nats.hook", "nats.publish", "http.webhook", "http.response", "python.transform",
}, ids);
}
[Fact]
public async Task Connection_providers_returns_registered_providers_empty_in_plan_1()
public async Task Connection_providers_returns_nats()
{
var c = await LoggedIn();
var res = await c.GetFromJsonAsync<List<ConnectionProviderDto>>("/api/connection-providers");
Assert.NotNull(res);
Assert.Empty(res!);
Assert.Contains(res!, p => p.Id == "nats");
}
private sealed record NodeTypeDto(string Id, string DisplayName, string Category,

View File

@@ -16,7 +16,7 @@ public class ExecutionsEndpointsTests : IClassFixture<WebFactory>
return c;
}
[Fact(Skip = "Enabled after Tasks 22-23 land WebhookNode and WebResponseNode, and Task 24 DI-registers them")]
[Fact]
public async Task Manual_run_of_workflow_with_single_webhook_trigger_produces_completed_execution()
{
var c = await LoggedIn();

View File

@@ -18,7 +18,7 @@ public class TriggerHostTests : IClassFixture<WebFactory>
return c;
}
[Fact(Skip = "Enabled after Task 24 DI-registers WebhookNode")]
[Fact]
public async Task Activating_a_workflow_registers_its_webhook_and_deactivating_unregisters_it()
{
var c = await LoggedIn();