Files
wx-win-agent/tests/node-agent/WxAgent.Service.Tests/ServiceTests.cs
T

84 lines
5.4 KiB
C#

using System.Net;
using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Text;
using System.Text.Json;
using Microsoft.AspNetCore.TestHost;
using WxAgent.Service;
using Xunit;
namespace WxAgent.Service.Tests;
public sealed class ServiceTests
{
private sealed class Backend : IAgentBackend
{
public IReadOnlyList<AgentCapability> Capabilities =>
[
new("agent-status", true, true, true, false, false, "read", false, 30, null, []),
new("accounts-list", true, true, true, false, false, "read", false, 30, null, []),
new("sessions-list", true, true, true, false, false, "read", false, 30, null, []),
new("messages-read", true, true, true, true, false, "read", false, 30, null, []),
new("contacts-list", true, true, true, false, false, "read", false, 30, null, []),
new("listener-events", true, true, true, true, false, "read", false, 30, null, [])
];
public Task<object> StatusAsync(CancellationToken cancellationToken) => Task.FromResult<object>(new { online = true, wechatAvailable = false });
}
[Fact]
public async Task RealRoutesAndMcpShareCredentialsAndRejectRevokedBrowserSession()
{
var directory = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N"));
Directory.CreateDirectory(directory);
var token = new string('A', 43);
var options = new ServiceOptions { CredentialFile = Path.Combine(directory, "credentials.json"), DataDirectory = directory };
void Rotate(string value) => File.WriteAllText(options.CredentialFile,
JsonSerializer.Serialize(new[] { new ServiceCredential("alice", ServiceOptions.HashToken(value), ["read"], []) }));
Rotate(token);
await using var app = ServiceHost.Build(options, new Backend(), b => b.WebHost.UseTestServer());
try
{
await app.StartAsync();
using var client = app.GetTestClient();
client.BaseAddress = new Uri("http://localhost:5088");
Assert.Equal(HttpStatusCode.Unauthorized, (await client.GetAsync("/api/v1/status")).StatusCode);
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
Assert.Equal(HttpStatusCode.OK, (await client.GetAsync("/api/v1/status")).StatusCode);
client.DefaultRequestHeaders.Add("Origin", "http://evil.invalid");
Assert.Equal(HttpStatusCode.Forbidden, (await client.GetAsync("/api/v1/status")).StatusCode);
client.DefaultRequestHeaders.Remove("Origin");
client.DefaultRequestHeaders.Host = "evil.invalid";
Assert.Equal(HttpStatusCode.Forbidden, (await client.GetAsync("/api/v1/status")).StatusCode);
client.DefaultRequestHeaders.Host = null;
client.DefaultRequestHeaders.Accept.ParseAdd("application/json");
client.DefaultRequestHeaders.Accept.ParseAdd("text/event-stream");
using var initialize = await client.PostAsJsonAsync("/mcp", new { jsonrpc = "2.0", id = 1, method = "initialize", @params = new { protocolVersion = "2025-11-25", capabilities = new { }, clientInfo = new { name = "wxagent-integration", version = "1" } } });
Assert.Equal(HttpStatusCode.OK, initialize.StatusCode);
using var list = await client.PostAsJsonAsync("/mcp", new { jsonrpc = "2.0", id = 2, method = "tools/list" });
var schema = await list.Content.ReadAsStringAsync();
Assert.Equal(HttpStatusCode.OK, list.StatusCode);
Assert.Contains("agent_status", schema);
Assert.Contains("inputSchema", schema);
using var call = await client.PostAsJsonAsync("/mcp", new { jsonrpc = "2.0", id = 3, method = "tools/call", @params = new { name = "agent_status", arguments = new { } } });
Assert.Equal(HttpStatusCode.OK, call.StatusCode);
Assert.Contains("wechatAvailable", await call.Content.ReadAsStringAsync());
client.DefaultRequestHeaders.Authorization = null;
client.DefaultRequestHeaders.Add("Origin", "http://localhost:5088");
using var login = await client.PostAsJsonAsync("/api/v1/login", new { token });
Assert.Equal(HttpStatusCode.OK, login.StatusCode);
var cookie = login.Headers.GetValues("Set-Cookie").Single().Split(';')[0];
var result = await login.Content.ReadFromJsonAsync<JsonElement>();
client.DefaultRequestHeaders.Add("Cookie", cookie);
Assert.Equal(HttpStatusCode.Forbidden, (await client.PostAsync("/api/v1/logout", null)).StatusCode);
Assert.Equal(HttpStatusCode.OK, (await client.GetAsync("/api/v1/status")).StatusCode);
Rotate(new string('B', 43));
Assert.Equal(HttpStatusCode.Unauthorized, (await client.GetAsync("/api/v1/status")).StatusCode);
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
Assert.Equal(HttpStatusCode.Unauthorized, (await client.PostAsJsonAsync("/mcp", new { jsonrpc = "2.0", id = 4, method = "tools/list" })).StatusCode);
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", new string('B', 43));
Assert.Equal(HttpStatusCode.OK, (await client.GetAsync("/api/v1/status")).StatusCode);
}
finally { await app.StopAsync(); Directory.Delete(directory, true); }
}
}