feat: integrate client and server sharing workflows

This commit is contained in:
justme committed 2026-10-02 10:49:45 +08:00
1 parent 42b93ae2d8
commit 7406e2fe37
101 files changed
+3153 -253

No files matched your search

@@ -1,5 +1,7 @@
using System.Net;
using System.Security.Cryptography;
using System.Text.Json;
using WebDrop.Api;
using WebDrop.Core;
using static WebDrop.Api.Tests.ServerFixture;
@@ -17,6 +19,7 @@ public class RestTests(ServerFixture s) : IClassFixture<ServerFixture>
var json = await ReadJsonAsync(resp);
Assert.Equal(1, json.GetProperty("protocol").GetInt32());
Assert.Equal(ApiContract.Version, json.GetProperty("contract_version").GetString());
Assert.True(json.GetProperty("transports").GetProperty("websocket").GetBoolean());
Assert.Equal(1048592, json.GetProperty("limits").GetProperty("max_payload_bytes").GetInt32());
// 默认不启用验证码,不下发 Cap 的地址
@@ -89,6 +92,31 @@ public class RestTests(ServerFixture s) : IClassFixture<ServerFixture>
await AssertErrorAsync(await s.AppendAsync(ch, ch.Member, Small(NewId())), 403, "not_joined");
}
[Fact]
public async Task OwnerCapabilityCanManageWithoutOccupyingAnotherSeat()
{
var ch = await s.CreateAsync();
using (var joined = await s.JoinAsync(ch, ch.Member)) Assert.Equal(HttpStatusCode.OK, joined.StatusCode);
var unseatedOwner = new Who("owner", ch.OwnerToken, RandomNumberGenerator.GetBytes(32));
async Task<HttpResponseMessage> OwnerRequest(HttpMethod method, string path, HttpContent? body = null)
{
using var request = s.Req(method, path, unseatedOwner, body);
request.Headers.Remove("X-WD-Endpoint");
return await s.Http.SendAsync(request);
}
using (var patch = await OwnerRequest(HttpMethod.Patch, $"/api/v1/channels/{ch.Id}/settings", JsonBody(new { seats = 3 })))
Assert.Equal(HttpStatusCode.OK, patch.StatusCode);
using (var seats = await OwnerRequest(HttpMethod.Get, $"/api/v1/channels/{ch.Id}/seats"))
Assert.Equal(HttpStatusCode.OK, seats.StatusCode);
using (var absentSeat = await OwnerRequest(HttpMethod.Delete,
$"/api/v1/channels/{ch.Id}/seats/{B64(RandomNumberGenerator.GetBytes(32))}"))
await AssertErrorAsync(absentSeat, 404, "not_found");
using (var deleted = await OwnerRequest(HttpMethod.Delete, $"/api/v1/channels/{ch.Id}"))
Assert.Equal(HttpStatusCode.NoContent, deleted.StatusCode);
await AssertErrorAsync(await s.Http.SendAsync(s.Req(HttpMethod.Get, $"/api/v1/channels/{ch.Id}", ch.Owner)), 404, "not_found");
}
[Fact]
public async Task AppendIsIdempotentOverHttp()
{
@@ -287,6 +315,7 @@ public class RestTests(ServerFixture s) : IClassFixture<ServerFixture>
public async Task DeleteChannelRemovesIt()
{
var ch = await s.CreateAsync();
using (var joined = await s.JoinAsync(ch, ch.Member)) Assert.Equal(HttpStatusCode.OK, joined.StatusCode);
await s.AppendAsync(ch, ch.Owner, Small(NewId()));
await AssertErrorAsync(await s.Http.SendAsync(s.Req(HttpMethod.Delete, $"/api/v1/channels/{ch.Id}", ch.Member)), 403, "forbidden");