mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-10-27 15:01:07 -04:00
The desktop needs a cross-platform way to read and save sets and to turn one into nests before any UI is built on it. RemoteDrawingSetStore covers every /api/sets route with the library client's checks and conflict handling. SetReleasePlan groups a set by material, grade, thickness, units and cut type without I/O, so the release dialog can preview refusals (duplicate names, drawings without material) before anything is created. SetReleaseSession builds every group's nest through LibraryDrawingInsert before uploading any, so a refusal leaves nothing on the server; uploads then never cancel mid-flight, a lost reply is reconciled by the nest's client-allocated id, and the release is posted only when every chosen nest exists, with a same-id retry when that post fails. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
119 lines
4.5 KiB
C#
119 lines
4.5 KiB
C#
using System.Net;
|
|
using OpenNest.Data;
|
|
|
|
namespace OpenNest.Tests.Data;
|
|
|
|
public class RemoteDrawingSetStoreTests
|
|
{
|
|
private static RemoteDrawingSetStore Store(StubHandler handler) =>
|
|
new(new HttpClient(handler), "http://server:8090/base/");
|
|
|
|
private static DrawingSetRecord Set(Guid? drawing = null) => new()
|
|
{
|
|
Id = Guid.NewGuid(),
|
|
Name = "Synthetic kit",
|
|
Members = new[] { new DrawingSetMember { DrawingId = drawing ?? Guid.NewGuid(), Quantity = 2 } },
|
|
};
|
|
|
|
[Fact]
|
|
public async Task QueryAsync_SendsEscapedFilters()
|
|
{
|
|
var handler = new StubHandler(_ => StubHandler.Json(new { items = Array.Empty<object>(), total = 0, offset = 5, limit = 5 }));
|
|
using var store = Store(handler);
|
|
|
|
await store.QueryAsync(new DrawingSetQuery
|
|
{
|
|
Search = " 50%_ ",
|
|
Customer = "A&B",
|
|
IncludeArchived = true,
|
|
Sort = DrawingSetSortField.Customer,
|
|
Descending = false,
|
|
Offset = 5,
|
|
Limit = 5,
|
|
});
|
|
|
|
Assert.Equal(
|
|
"http://server:8090/base/api/sets/query?search=50%25_&sort=customer&order=asc&offset=5&limit=5&customer=A%26B&includeArchived=true",
|
|
handler.Requests.Single().RequestUri!.AbsoluteUri);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task OldServer_RaisesServerTooOld()
|
|
{
|
|
using var store = Store(new StubHandler(_ => new HttpResponseMessage(HttpStatusCode.NotFound)));
|
|
|
|
var query = await Assert.ThrowsAsync<ServerTooOldException>(() => store.QueryAsync(new DrawingSetQuery()));
|
|
await Assert.ThrowsAsync<ServerTooOldException>(() => store.GetAsync(Guid.NewGuid()));
|
|
await Assert.ThrowsAsync<ServerTooOldException>(() => store.GetReleaseForNestAsync(Guid.NewGuid()));
|
|
Assert.Contains("drawing sets", query.Message);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task UnknownSet_OnASetAwareServer_IsNull()
|
|
{
|
|
var handler = new StubHandler(request => request.RequestUri!.AbsolutePath.EndsWith("/api/sets/query")
|
|
? StubHandler.Json(new { items = Array.Empty<object>(), total = 0, offset = 0, limit = 1 })
|
|
: new HttpResponseMessage(HttpStatusCode.NotFound));
|
|
using var store = Store(handler);
|
|
|
|
Assert.Null(await store.GetAsync(Guid.NewGuid()));
|
|
Assert.EndsWith("api/sets/query?limit=1", handler.Requests[1].RequestUri!.AbsoluteUri);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task InvalidSet_IsRefusedBeforeSending()
|
|
{
|
|
var handler = new StubHandler(_ => throw new InvalidOperationException("Nothing may be sent."));
|
|
using var store = Store(handler);
|
|
var duplicate = Set();
|
|
duplicate.Members = duplicate.Members.Concat(duplicate.Members).ToList();
|
|
|
|
await Assert.ThrowsAsync<ArgumentException>(() => store.CreateAsync(duplicate));
|
|
await Assert.ThrowsAsync<ArgumentException>(() => store.PostReleaseAsync(Guid.NewGuid(),
|
|
new SetReleaseRecord { Id = Guid.NewGuid(), SetRevision = 1, Multiplier = 0 }));
|
|
Assert.Empty(handler.Requests);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task CreateAsync_SendsMembersWithoutJoinedDrawingsAndChecksTheReply()
|
|
{
|
|
var drawing = Guid.NewGuid();
|
|
var set = Set(drawing);
|
|
set.Members[0].Drawing = new DrawingLibraryRecord { Id = drawing, Name = "Synthetic joined" };
|
|
var handler = new StubHandler(_ => StubHandler.Json(new
|
|
{
|
|
id = set.Id,
|
|
revision = 1,
|
|
name = set.Name,
|
|
members = new[] { new { drawingId = drawing, quantity = 3 } },
|
|
}));
|
|
using var store = Store(handler);
|
|
|
|
await Assert.ThrowsAsync<IOException>(() => store.CreateAsync(set));
|
|
Assert.DoesNotContain("Synthetic joined", handler.RequestBodies.Single());
|
|
}
|
|
|
|
[Fact]
|
|
public async Task PostReleaseAsync_ReplyForOtherNests_IsRefused()
|
|
{
|
|
var setId = Guid.NewGuid();
|
|
var release = new SetReleaseRecord
|
|
{
|
|
Id = Guid.NewGuid(),
|
|
SetRevision = 1,
|
|
Multiplier = 1,
|
|
Nests = new[] { new SetReleaseNest { NestId = Guid.NewGuid(), MaterialName = "Synthetic Steel" } },
|
|
};
|
|
var handler = new StubHandler(_ => StubHandler.Json(new
|
|
{
|
|
id = release.Id,
|
|
setId,
|
|
setRevision = 1,
|
|
nests = new[] { new { nestId = Guid.NewGuid() } },
|
|
}));
|
|
using var store = Store(handler);
|
|
|
|
await Assert.ThrowsAsync<IOException>(() => store.PostReleaseAsync(setId, release));
|
|
}
|
|
}
|