using OpenNest.CNC.CuttingStrategy;
using OpenNest.Data;
using OpenNest.Geometry;
using OpenNest.IO;
using OpenNest.Shapes;
namespace OpenNest.Server.Tests;
///
/// The whole release path: code-built drawings in two materials are packaged into the
/// library, collected into a set, released ×2 through the real clients, and the nests and
/// release record are read back from the production routes.
///
public sealed class SetReleaseEndToEndTests
{
private static Drawing SyntheticDrawing(string name, double length)
{
var drawing = new RectangleShape { Name = name, Length = length, Width = 2 }.GetDrawing();
drawing.CutPins.Add(new ContourCutPin(new Vector(length, 2), new LineLeadIn { Length = 0.25 }, new NoLeadOut(),
new NormalTab { Size = 0.03 }));
return drawing;
}
private static async Task Store(RemoteDrawingLibrary library, string name, double length,
string material, CutType cutType)
{
var record = new DrawingLibraryRecord
{
Id = Guid.NewGuid(),
Name = name,
Customer = "Synthetic customer",
MaterialName = material,
MaterialGrade = "Grade A",
Thickness = 0.25,
Units = Units.Inches,
CutType = cutType,
SavedBy = "Synthetic operator",
};
return await library.UploadAsync(record, DrawingPackage.Write(SyntheticDrawing(name, length), Units.Inches));
}
private static byte[] Write(Nest nest)
{
using var stream = new MemoryStream();
new NestWriter(nest).Write(stream);
return stream.ToArray();
}
private static Nest Read(byte[] archive)
{
using var stream = new MemoryStream(archive, writable: false);
return new NestReader(stream).Read();
}
[Fact]
public async Task Release_MakesOneDraftNestPerMaterialAndRecordsThem()
{
using var factory = new ServerFactory();
using var client = factory.CreateClient();
var url = client.BaseAddress!.ToString();
using var library = new RemoteDrawingLibrary(client, url);
using var sets = new RemoteDrawingSetStore(client, url);
using var nests = new RemoteNestRepository(client, url);
var a = await Store(library, "SYN-A", 4, "Synthetic Steel", CutType.Laser);
var b = await Store(library, "SYN-B", 5, "Synthetic Steel", CutType.Laser);
var c = await Store(library, "SYN-C", 6, "Synthetic Aluminum", CutType.Waterjet);
var created = await sets.CreateAsync(new DrawingSetRecord
{
Id = Guid.NewGuid(),
Name = "Synthetic kit",
Customer = "Synthetic set customer",
Members = new[] { (a, 3), (b, 1), (c, 2) }
.Select(m => new DrawingSetMember { DrawingId = m.Item1.Id, Quantity = m.Item2 }).ToList(),
});
var set = await sets.GetAsync(created.Id);
var plan = SetReleasePlan.Build(set!, 2, includeArchived: false);
var number = 0;
var session = new SetReleaseSession(sets, library, nests, url,
bytes =>
{
var contents = DrawingPackage.Read(bytes);
return new LibraryPackage(bytes, contents.Drawing, contents.Units, contents.Warnings);
},
Write,
(group, _) => Task.FromResult(new Nest($"Synthetic release {++number}") { Units = group.Units }));
var result = await session.RunAsync(plan, plan.Groups, "Synthetic operator", "Synthetic release notes");
Assert.Equal("", result.ReleaseError);
Assert.Equal(2, result.Created.Count);
foreach (var group in result.Groups)
{
var stored = Read((await nests.GetFileAsync(group.Record!.Id))!);
Assert.Equal(NestStatus.Draft, (await nests.GetMetadataAsync(group.Record.Id))!.Status);
Assert.Equal((NestStatus.Draft, group.Group.MaterialName, 0.25, "Synthetic set customer"),
(stored.Status, stored.Material.Name, stored.Thickness, stored.Customer));
foreach (var item in group.Group.Items)
{
var drawing = stored.Drawings.Single(d => d.Name == item.Drawing.Name);
Assert.Equal(item.Member.Quantity * 2, drawing.Quantity.Required);
Assert.Equal((item.Drawing.Id, 1, url.TrimEnd('/')), (drawing.Library!.Id, drawing.Library.Revision, drawing.Library.ServerKey));
Assert.Single(drawing.CutPins);
}
}
var steel = result.Groups.Single(g => g.Group.MaterialName == "Synthetic Steel");
Assert.Equal(new[] { "SYN-A", "SYN-B" }, steel.Group.Items.Select(i => i.Drawing.Name));
var releases = await sets.GetReleasesAsync(created.Id);
var release = Assert.Single(releases!.Items);
Assert.Equal((result.Release!.Id, 1, 2, "Synthetic release notes"),
(release.Id, release.SetRevision, release.Multiplier, release.Notes));
Assert.Equal(result.Groups.Select(g => g.Record!.Id), release.Nests.Select(n => n.NestId));
Assert.All(release.Nests, n => Assert.Equal(NestStatus.Draft, n.Nest!.Status));
Assert.Equal(CutType.Waterjet, release.Nests.Single(n => n.MaterialName == "Synthetic Aluminum").CutType);
Assert.Equal(release.Id, (await sets.GetReleaseForNestAsync(steel.Record!.Id))!.Id);
}
}