mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-11-08 12:35:44 -05:00
Moves the long workflow handlers into OpenNest/Forms/Commands: AutoNestCommand (dialog, owned modal progress, solve, validation review, commit and result notices), PostCommand (prepare, configure, verify, save dialog, multi-file overwrite confirmation) and NestStorageController (database open/save/save-as with reconciliation and storage errors). MainForm keeps the busy guards, the nesting lockout and nestingCts, and reacts to the controller's StateChanged to lock storage settings and saving. The characterization test now flips the controller's IsSaving instead of the removed databaseSaveInProgress field. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
135 lines
5.5 KiB
C#
135 lines
5.5 KiB
C#
using System.Reflection;
|
|
using OpenNest.Controls;
|
|
using OpenNest.Forms;
|
|
using OpenNest.Geometry;
|
|
|
|
namespace OpenNest.WinForms.Tests.Forms;
|
|
|
|
// Pins MainForm behaviour that its refactor must preserve: nest naming and the deliberately
|
|
// different busy guards. Reads Application.OpenForms, so it must not overlap fill-lifetime tests.
|
|
[Collection("Fill operation lifetime")]
|
|
public class MainFormCharacterizationTests
|
|
{
|
|
[Theory]
|
|
[InlineData(0, "N26-222")]
|
|
[InlineData(1, "N26-223")]
|
|
[InlineData(29, "N26-22Z")]
|
|
[InlineData(30, "N26-232")]
|
|
[InlineData(900, "N26-322")]
|
|
[InlineData(27000, "N26-3222")]
|
|
public void NestNamesUseTwoDigitYearAndPaddedBase30Sequence(int id, string expected) =>
|
|
StaTestThread.Run(() =>
|
|
{
|
|
using var host = new Host();
|
|
var name = (string)typeof(MainForm)
|
|
.GetMethod("GetNestName", BindingFlags.Instance | BindingFlags.NonPublic)!
|
|
.Invoke(host, [new DateTime(2026, 10, 17), id])!;
|
|
|
|
Assert.Equal(expected, name);
|
|
}, TimeSpan.FromMinutes(1), "The STA test did not complete.");
|
|
|
|
[Fact]
|
|
public void BusyGuardsDifferInWhichOperationsTheyCount() => StaTestThread.Run(() =>
|
|
{
|
|
using var host = new Host();
|
|
host.Show();
|
|
var nest = new Nest("guards");
|
|
var plate = nest.CreatePlate();
|
|
plate.Size = new Size(100, 100);
|
|
plate.Parts.Add(new Part(new Drawing("left", Square()), new Vector(1, 1)));
|
|
plate.Parts.Add(new Part(new Drawing("right", Square()), new Vector(12, 1)));
|
|
using var editor = new EditNestForm(nest) { MdiParent = host };
|
|
editor.PlateView.SetOverlapAutoCheck(null);
|
|
editor.Show();
|
|
editor.Activate();
|
|
editor.PlateManager.LoadAt(0);
|
|
var other = new Nest("other");
|
|
other.CreatePlate().Size = new Size(100, 100);
|
|
using var otherEditor = new EditNestForm(other) { MdiParent = host };
|
|
otherEditor.PlateView.SetOverlapAutoCheck(null);
|
|
otherEditor.Show();
|
|
otherEditor.PlateManager.LoadAt(0);
|
|
var views = new[] { editor.PlateView };
|
|
|
|
Assert.Equal(new Guards(false, false, false, false), Read(host, editor, views));
|
|
|
|
// Whole-job nesting blocks every guard.
|
|
SetField(host, "nestingInProgress", true);
|
|
Assert.Equal(new Guards(true, true, true, true), Read(host, editor, views));
|
|
SetField(host, "nestingInProgress", false);
|
|
|
|
// A database save only blocks the report snapshot.
|
|
var storage = GetField(host, "storage");
|
|
SetBackingField(storage, "IsSaving", true);
|
|
Assert.Equal(new Guards(false, false, false, true), Read(host, editor, views));
|
|
SetBackingField(storage, "IsSaving", false);
|
|
|
|
// A fill on a view of the nest blocks the plate guards but not the report.
|
|
SetBackingField(editor.PlateView, "IsFillInProgress", true);
|
|
try
|
|
{
|
|
Assert.Equal(new Guards(true, true, true, false), Read(host, editor, views));
|
|
}
|
|
finally
|
|
{
|
|
SetBackingField(editor.PlateView, "IsFillInProgress", false);
|
|
}
|
|
|
|
// A fill on another nest's view blocks nothing for this nest.
|
|
SetBackingField(otherEditor.PlateView, "IsFillInProgress", true);
|
|
try
|
|
{
|
|
Assert.Equal(new Guards(false, false, false, false), Read(host, editor, views));
|
|
}
|
|
finally
|
|
{
|
|
SetBackingField(otherEditor.PlateView, "IsFillInProgress", false);
|
|
}
|
|
|
|
// A busy plate action (selection) blocks only the cutting-plan guard.
|
|
editor.PlateView.SelectAll();
|
|
Assert.True(editor.PlateView.Actions.CurrentAction?.IsBusy() == true);
|
|
Assert.Equal(new Guards(false, true, false, false), Read(host, editor, views));
|
|
}, TimeSpan.FromMinutes(1), "The STA test did not complete.");
|
|
|
|
private sealed record Guards(bool ExpandSpacing, bool CuttingPlan, bool Clamps, bool NestJob);
|
|
|
|
private static Guards Read(MainForm host, EditNestForm editor, PlateView[] views) => new(
|
|
host.IsExpandSpacingBusy(editor),
|
|
host.IsCuttingPlanBusy(views),
|
|
(bool)Invoke(host, "ClampsInUse", editor.Nest),
|
|
(bool)Invoke(host, "IsNestJobBusy"));
|
|
|
|
private static object Invoke(MainForm host, string name, params object[] args) =>
|
|
typeof(MainForm).GetMethod(name, BindingFlags.Instance | BindingFlags.NonPublic)!.Invoke(host, args)!;
|
|
|
|
private static object GetField(MainForm host, string name) =>
|
|
typeof(MainForm).GetField(name, BindingFlags.Instance | BindingFlags.NonPublic)!.GetValue(host)!;
|
|
|
|
private static void SetField(MainForm host, string name, object value) =>
|
|
typeof(MainForm).GetField(name, BindingFlags.Instance | BindingFlags.NonPublic)!.SetValue(host, value);
|
|
|
|
private static void SetBackingField(object target, string property, object value) =>
|
|
target.GetType()
|
|
.GetField($"<{property}>k__BackingField", BindingFlags.Instance | BindingFlags.NonPublic)!
|
|
.SetValue(target, value);
|
|
|
|
private static CNC.Program Square()
|
|
{
|
|
var program = new CNC.Program();
|
|
program.MoveTo(0, 0);
|
|
program.LineTo(0, 10);
|
|
program.LineTo(10, 10);
|
|
program.LineTo(10, 0);
|
|
program.LineTo(0, 0);
|
|
return program;
|
|
}
|
|
|
|
private sealed class Host : MainForm
|
|
{
|
|
// No startup migrations/automatic new document, and no settings save at close.
|
|
protected override void OnLoad(EventArgs e) { }
|
|
protected override void OnClosing(System.ComponentModel.CancelEventArgs e) { }
|
|
}
|
|
}
|