节点在线、应用在线、配置在线使用令牌查询
大石头 authored at 2021-12-16 19:49:30
4.73 KiB
Stardust
using System.Text.Json;
using Stardust.WebApiTests.Fixtures;
using Xunit;
using Xunit.Abstractions;

namespace Stardust.WebApiTests.Areas;

/// <summary>
/// AgentController 路由别名集成测试(lead 裁定 A 双路由,2026-11-10 P2)。
/// </summary>
/// <remarks>
/// 背景:WebApi 根目录 AgentController 仅有裸路由 /Agent、/Agent/Probe,不符 WebApi api/[controller] 惯例,
/// Vue 请求层按 routeToApiPrefix 拼 /api 后 404(j-node-b task-51 走查抓出,修前证据帧 F-NODE-AGENT-ROUTE)。
/// 前置兼容性 grep:仓内硬编码裸 6681 消费者=0;SVR-安装引导页.md:125「/Agent?format=json 保持旧接口不变,
/// 兼容存量客户端」为仓外契约面 → lead 19:2x 裁定 A:双路由并存(裸旧路径保留 + /api 惯例别名新增),
/// ConfigController 不动(configCenter 前端修已闭其面)。
/// 断言语义:双路径各返回 200 + code=0 信封;探活端点不校验 online 值(依赖本机 Agent 环境)。
/// </remarks>
[Collection(WebApiCollection.Name)]
public class AgentRouteTests
{
    private readonly WebApiTestFactory _factory;
    private readonly ApiClient _api;
    private readonly ITestOutputHelper _output;

    public AgentRouteTests(WebApiTestFactory factory, ITestOutputHelper output)
    {
        _factory = factory;
        _api = new ApiClient(factory, output);
        _output = output;
    }

    private static async Task<JsonElement> BodyOf(HttpResponseMessage resp)
    {
        var body = await resp.Content.ReadAsStringAsync();
        return JsonSerializer.Deserialize<JsonElement>(body, new JsonSerializerOptions(JsonSerializerDefaults.Web));
    }

    private async Task<HttpResponseMessage> AnonymousGetAsync(String path)
    {
        var resp = await _api.GetAsync(path, auth: false);
        var body = await resp.Content.ReadAsStringAsync();
        _output.WriteLine("GET " + path + " HTTP " + (Int32)resp.StatusCode + " body=" + body);
        return resp;
    }

    /// <summary>裸 /Agent 旧接口承诺保留:下载目录 JSON,200 + code=0 信封。</summary>
    [Fact]
    public async Task Index_BareRoute_Returns200Envelope()
    {
        var resp = await AnonymousGetAsync("/Agent");

        Assert.True((Int32)resp.StatusCode == 200, "裸 /Agent 旧接口应 200(SVR-安装引导页.md:125 承诺),实际 " + (Int32)resp.StatusCode);
        var body = await BodyOf(resp);
        Assert.True(body.TryGetProperty("code", out var c) && c.GetInt32() == 0, "应返回 code=0 信封:" + body);
        Assert.True(body.TryGetProperty("data", out var data) && data.TryGetProperty("agent", out _), "data.agent 下载清单应存在:" + body);
    }

    /// <summary>/api/Agent 惯例别名(裁定 A 新增):与裸路由同语义,200 + code=0 信封。</summary>
    [Fact]
    public async Task Index_ApiPrefixRoute_Returns200Envelope()
    {
        var resp = await AnonymousGetAsync("/api/Agent");

        Assert.True((Int32)resp.StatusCode == 200, "/api/Agent 惯例别名应 200(Vue 请求层按惯例拼 /api),实际 " + (Int32)resp.StatusCode);
        var body = await BodyOf(resp);
        Assert.True(body.TryGetProperty("code", out var c) && c.GetInt32() == 0, "应返回 code=0 信封:" + body);
        Assert.True(body.TryGetProperty("data", out var data) && data.TryGetProperty("agent", out _), "data.agent 下载清单应存在:" + body);
    }

    /// <summary>裸 /Agent/Probe 旧接口承诺保留:本机探活,200 + code=0(online 值依赖本机 Agent,不校验)。</summary>
    [Fact]
    public async Task Probe_BareRoute_Returns200Envelope()
    {
        var resp = await AnonymousGetAsync("/Agent/Probe");

        Assert.True((Int32)resp.StatusCode == 200, "裸 /Agent/Probe 旧接口应 200,实际 " + (Int32)resp.StatusCode);
        var body = await BodyOf(resp);
        Assert.True(body.TryGetProperty("code", out var c) && c.GetInt32() == 0, "应返回 code=0 信封:" + body);
        Assert.True(body.TryGetProperty("data", out var data) && data.TryGetProperty("online", out _), "data.online 应存在:" + body);
    }

    /// <summary>/api/Agent/Probe 惯例别名(裁定 A 新增):与裸路由同语义。</summary>
    [Fact]
    public async Task Probe_ApiPrefixRoute_Returns200Envelope()
    {
        var resp = await AnonymousGetAsync("/api/Agent/Probe");

        Assert.True((Int32)resp.StatusCode == 200, "/api/Agent/Probe 惯例别名应 200,实际 " + (Int32)resp.StatusCode);
        var body = await BodyOf(resp);
        Assert.True(body.TryGetProperty("code", out var c) && c.GetInt32() == 0, "应返回 code=0 信封:" + body);
        Assert.True(body.TryGetProperty("data", out var data) && data.TryGetProperty("online", out _), "data.online 应存在:" + body);
    }
}