feat(dotnet): add galaxy-browse CLI (§4.6); chore: verify version subcommand (§4.4)
This commit is contained in:
@@ -360,6 +360,146 @@ public sealed class MxGatewayClientCliTests
|
||||
Assert.Equal(string.Empty, error.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies galaxy-browse walks root objects and eagerly expands one further
|
||||
/// level when --depth 1 is passed, printing an indented tree.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task RunAsync_GalaxyBrowse_TextTreeExpandsToDepth()
|
||||
{
|
||||
using var output = new StringWriter();
|
||||
using var error = new StringWriter();
|
||||
FakeCliClient fakeClient = new();
|
||||
// Root level (parent 0): one area with a child hint.
|
||||
fakeClient.GalaxyBrowseChildrenReplies[0] = new Queue<BrowseChildrenReply>(
|
||||
[
|
||||
new BrowseChildrenReply
|
||||
{
|
||||
Children = { new GalaxyObject { GobjectId = 10, TagName = "Area_001", BrowseName = "Area" } },
|
||||
ChildHasChildren = { true },
|
||||
},
|
||||
]);
|
||||
// Children of gobject 10.
|
||||
fakeClient.GalaxyBrowseChildrenReplies[10] = new Queue<BrowseChildrenReply>(
|
||||
[
|
||||
new BrowseChildrenReply
|
||||
{
|
||||
Children = { new GalaxyObject { GobjectId = 20, TagName = "Tank_001", BrowseName = "Tank" } },
|
||||
},
|
||||
]);
|
||||
|
||||
int exitCode = await MxGatewayClientCli.RunAsync(
|
||||
[
|
||||
"galaxy-browse",
|
||||
"--endpoint",
|
||||
"http://localhost:5000",
|
||||
"--api-key",
|
||||
"test-api-key",
|
||||
"--depth",
|
||||
"1",
|
||||
],
|
||||
output,
|
||||
error,
|
||||
_ => fakeClient);
|
||||
|
||||
Assert.Equal(0, exitCode);
|
||||
string text = output.ToString();
|
||||
Assert.Contains("Area_001", text);
|
||||
Assert.Contains("Tank_001", text);
|
||||
// Children are indented beneath their parent (two-space indent per level).
|
||||
Assert.Matches(@"\n \d+\tTank_001", text);
|
||||
// Root fetched with the parent oneof unset; child fetch used parent 10.
|
||||
Assert.Contains(
|
||||
fakeClient.GalaxyBrowseChildrenRequests,
|
||||
request => request.ParentCase == BrowseChildrenRequest.ParentOneofCase.ParentGobjectId
|
||||
&& request.ParentGobjectId == 10);
|
||||
Assert.Equal(string.Empty, error.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies galaxy-browse --json emits a nested JSON document and forwards
|
||||
/// the filter flags onto the BrowseChildren request.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task RunAsync_GalaxyBrowse_JsonForwardsFilters()
|
||||
{
|
||||
using var output = new StringWriter();
|
||||
using var error = new StringWriter();
|
||||
FakeCliClient fakeClient = new();
|
||||
fakeClient.GalaxyBrowseChildrenReplies[0] = new Queue<BrowseChildrenReply>(
|
||||
[
|
||||
new BrowseChildrenReply
|
||||
{
|
||||
Children = { new GalaxyObject { GobjectId = 10, TagName = "Area_001", BrowseName = "Area" } },
|
||||
},
|
||||
]);
|
||||
|
||||
int exitCode = await MxGatewayClientCli.RunAsync(
|
||||
[
|
||||
"galaxy-browse",
|
||||
"--endpoint",
|
||||
"http://localhost:5000",
|
||||
"--api-key",
|
||||
"test-api-key",
|
||||
"--tag-name-glob",
|
||||
"Area*",
|
||||
"--alarm-bearing-only",
|
||||
"--json",
|
||||
],
|
||||
output,
|
||||
error,
|
||||
_ => fakeClient);
|
||||
|
||||
Assert.Equal(0, exitCode);
|
||||
using System.Text.Json.JsonDocument document = System.Text.Json.JsonDocument.Parse(output.ToString());
|
||||
Assert.Equal("galaxy-browse", document.RootElement.GetProperty("command").GetString());
|
||||
Assert.True(document.RootElement.GetProperty("nodes").GetArrayLength() >= 1);
|
||||
BrowseChildrenRequest request = Assert.Single(fakeClient.GalaxyBrowseChildrenRequests);
|
||||
Assert.Equal("Area*", request.TagNameGlob);
|
||||
Assert.True(request.AlarmBearingOnly);
|
||||
Assert.Equal(string.Empty, error.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies galaxy-browse --parent fetches exactly one level of children for
|
||||
/// the supplied gobject id via a parent-scoped BrowseChildren request.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task RunAsync_GalaxyBrowse_ParentFetchesSingleLevel()
|
||||
{
|
||||
using var output = new StringWriter();
|
||||
using var error = new StringWriter();
|
||||
FakeCliClient fakeClient = new();
|
||||
fakeClient.GalaxyBrowseChildrenReplies[10] = new Queue<BrowseChildrenReply>(
|
||||
[
|
||||
new BrowseChildrenReply
|
||||
{
|
||||
Children = { new GalaxyObject { GobjectId = 20, TagName = "Tank_001", BrowseName = "Tank" } },
|
||||
},
|
||||
]);
|
||||
|
||||
int exitCode = await MxGatewayClientCli.RunAsync(
|
||||
[
|
||||
"galaxy-browse",
|
||||
"--endpoint",
|
||||
"http://localhost:5000",
|
||||
"--api-key",
|
||||
"test-api-key",
|
||||
"--parent",
|
||||
"10",
|
||||
],
|
||||
output,
|
||||
error,
|
||||
_ => fakeClient);
|
||||
|
||||
Assert.Equal(0, exitCode);
|
||||
Assert.Contains("Tank_001", output.ToString());
|
||||
BrowseChildrenRequest request = Assert.Single(fakeClient.GalaxyBrowseChildrenRequests);
|
||||
Assert.Equal(BrowseChildrenRequest.ParentOneofCase.ParentGobjectId, request.ParentCase);
|
||||
Assert.Equal(10, request.ParentGobjectId);
|
||||
Assert.Equal(string.Empty, error.ToString());
|
||||
}
|
||||
|
||||
/// <summary>Verifies that galaxy-watch command prints text output for deploy events.</summary>
|
||||
[Fact]
|
||||
public async Task RunAsync_GalaxyWatch_PrintsTextOutputForEvents()
|
||||
@@ -1051,5 +1191,33 @@ public sealed class MxGatewayClientCliTests
|
||||
yield return deployEvent;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>List of received galaxy browse-children requests, in call order.</summary>
|
||||
public List<BrowseChildrenRequest> GalaxyBrowseChildrenRequests { get; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// Per-parent browse-children replies keyed by <c>parent_gobject_id</c>
|
||||
/// (0 = root). Each parent's queue is dequeued in page order; an absent
|
||||
/// or exhausted queue yields an empty reply.
|
||||
/// </summary>
|
||||
public Dictionary<int, Queue<BrowseChildrenReply>> GalaxyBrowseChildrenReplies { get; } = [];
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<BrowseChildrenReply> GalaxyBrowseChildrenAsync(
|
||||
BrowseChildrenRequest request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
GalaxyBrowseChildrenRequests.Add(request);
|
||||
int parentId = request.ParentCase == BrowseChildrenRequest.ParentOneofCase.ParentGobjectId
|
||||
? request.ParentGobjectId
|
||||
: 0;
|
||||
if (GalaxyBrowseChildrenReplies.TryGetValue(parentId, out Queue<BrowseChildrenReply>? queue)
|
||||
&& queue.TryDequeue(out BrowseChildrenReply? reply))
|
||||
{
|
||||
return Task.FromResult(reply);
|
||||
}
|
||||
|
||||
return Task.FromResult(new BrowseChildrenReply());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user