namespace Northstar.ProtoTest;
using System.Text.Json;
using global::ProtoTest.Core;
public static class NorthstarTargets
{
public const string Api = "Northstar";
}
/// The organization provisioned for the current test, plus its owner token.
public sealed record NorthstarOrganizationContext(
string Tenant,
string OrganizationId,
string OwnerEmail,
string OwnerToken,
Uri ApiBaseUrl) : IProtoContext;
/// The member the test is currently acting as.
public sealed record NorthstarMemberContext(
string Id,
string Email,
string Role,
string Token) : IProtoContext;
public sealed record NorthstarScenarioContext(
string CorrelationId,
DateTimeOffset StartedAtUtc,
string TestName) : IProtoContext;
public sealed class ScenarioProbe
{
private readonly List _milestones = [];
public IReadOnlyList Milestones => _milestones;
public void Mark(string milestone) => _milestones.Add(milestone);
}
public sealed class ScenarioProbeInitializer : IProtoClientInitializer
{
public string Name => "ScenarioProbe";
public Task TryInitializeAsync(
ProtoExecutionContext context,
CancellationToken cancellationToken = default)
{
context.RegisterClient(new ScenarioProbe(), Name);
return Task.FromResult(true);
}
}
///
/// Stamps every test with a correlation id and a custom-client milestone trail, then publishes both as
/// an observation, an attachment and trace events.
///
public sealed class NorthstarScenarioHook : IProtoTestHook
{
public int Order => -1_000;
public Task BeforeTestAsync(ProtoExecutionContext context)
{
var scenario = new NorthstarScenarioContext(
$"scenario-{context.TestId}-{Guid.NewGuid():N}",
DateTimeOffset.UtcNow,
context.TestName);
context.SetContext(scenario);
context.Client("ScenarioProbe").Mark("scenario-started");
context.RecordObservation(
"Northstar",
"scenario.started",
scenario.CorrelationId,
new { context.TestId, context.TestName });
context.Trace.WriteEvent(
"northstar.scenario.begin",
"Begin correlated Northstar scenario",
"Northstar.ProtoTest",
outcome: ProtoTraceOutcome.Succeeded,
attributes: new Dictionary
{
["northstar.correlation_id"] = scenario.CorrelationId
});
return Task.CompletedTask;
}
public Task AfterTestAsync(ProtoExecutionContext context)
{
var scenario = context.Resolve();
var probe = context.Client("ScenarioProbe");
probe.Mark("scenario-completed");
var duration = DateTimeOffset.UtcNow - scenario.StartedAtUtc;
context.RecordObservation(
"Northstar",
"scenario.completed",
scenario.CorrelationId,
new { duration.TotalMilliseconds, probe.Milestones });
context.AddAttachment(
"scenario-summary.json",
JsonSerializer.Serialize(new
{
scenario.CorrelationId,
scenario.TestName,
DurationMs = duration.TotalMilliseconds,
probe.Milestones
}),
"application/json",
"Correlation and custom-client milestones for this Northstar scenario.");
context.Trace.WriteEvent(
"northstar.scenario.end",
"Complete correlated Northstar scenario",
"Northstar.ProtoTest",
outcome: ProtoTraceOutcome.Succeeded,
attributes: new Dictionary
{
["northstar.correlation_id"] = scenario.CorrelationId,
["northstar.duration_ms"] = duration.TotalMilliseconds.ToString("F1")
});
return Task.CompletedTask;
}
}