w4c-workflows-api/w4c-workflows-api.Tests/WorkflowDataHelpers.cs

134 lines
4.1 KiB
C#

using w4c_workflows.Data;
using w4c_workflows.Models;
using w4c_workflows.Services;
using Xunit;
namespace w4c_workflows.Tests;
/// <summary>Shared compile-and-persist helpers for lifecycle/dispatcher tests.</summary>
internal static class WorkflowDataHelpers
{
public const string LinearYaml = """
name: linear
mode: function
language: shell
entry: { file: root.sh }
tasks:
- id: a
parent: root
next: b
language: shell
entry: { file: a.sh }
- id: b
parent: root
language: shell
entry: { file: b.sh }
""";
public const string DurableYaml = """
name: durable
mode: durable
language: shell
entry: { file: root.sh }
tasks:
- id: a
parent: root
language: shell
entry: { file: a.sh }
""";
/// <summary>Three-task success chain where every chained task declares its own
/// compensation (<c>onError</c>) target, for saga reverse-compensation tests.</summary>
public const string SagaYaml = """
name: saga
mode: function
language: shell
entry: { file: root.sh }
tasks:
- id: a
parent: root
next: b
onError: compensate_a
language: shell
entry: { file: a.sh }
- id: b
parent: root
next: c
onError: compensate_b
language: shell
entry: { file: b.sh }
- id: c
parent: root
onError: compensate_c
language: shell
entry: { file: c.sh }
- id: compensate_a
parent: root
language: shell
entry: { file: compensate_a.sh }
- id: compensate_b
parent: root
language: shell
entry: { file: compensate_b.sh }
- id: compensate_c
parent: root
language: shell
entry: { file: compensate_c.sh }
""";
public static Workflow CompileAndSave(WorkflowsDbContext db, string tenantId, string yaml, string path = "workflows/linear.yaml")
{
var compiler = new WorkflowCompiler(new WorkflowValidator(new LanguageRegistry()));
var result = compiler.Compile(yaml, path, tenantId);
Assert.True(result.Success, string.Join("\n", result.Errors));
var workflow = result.Workflow!.Workflow;
workflow.Tasks = result.Workflow.Tasks.ToList();
db.Workflows.Add(workflow);
db.SaveChanges();
return workflow;
}
public static WorkflowTask TaskByKey(Workflow workflow, string key)
=> workflow.Tasks.Single(t => t.Key == key);
public static WorkflowRun AddPendingRun(WorkflowsDbContext db, Workflow workflow, string? input = null, Guid? startTaskId = null)
{
var run = new WorkflowRun
{
Id = Guid.NewGuid(),
WorkflowId = workflow.Id,
TenantId = workflow.TenantId,
Status = RunStatus.Pending,
TriggerJson = "{\"type\":\"event\"}",
InputJson = input,
CorrelationId = "test-correlation",
StartTaskId = startTaskId,
};
db.WorkflowRuns.Add(run);
db.SaveChanges();
return run;
}
/// <summary>Adds a run in a terminal/in-flight status with an explicit start time.</summary>
public static WorkflowRun AddRun(WorkflowsDbContext db, Workflow workflow, string status, DateTime? startedAt = null, DateTime? finishedAt = null, string? error = null)
{
var run = new WorkflowRun
{
Id = Guid.NewGuid(),
WorkflowId = workflow.Id,
TenantId = workflow.TenantId,
Status = status,
TriggerJson = "{\"type\":\"event\"}",
CorrelationId = $"corr-{Guid.NewGuid():N}",
StartedAt = startedAt,
FinishedAt = finishedAt,
Error = error,
};
db.WorkflowRuns.Add(run);
db.SaveChanges();
return run;
}
}