mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-11-03 12:21:39 -05:00
Desktop test classes each kept identical PumpUntil, Show, Mouse, All, PressKey, Raise, SetBackingField and Field helpers. They now import FormTesting and TestReflection; the two Field variants that read a base type's field or unwrap DrawingLibraryForm keep a one-line wrapper. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
209 lines
9.2 KiB
C#
209 lines
9.2 KiB
C#
using System.Reflection;
|
|
using System.Windows.Forms;
|
|
using OpenNest.Converters;
|
|
using OpenNest.Data;
|
|
using OpenNest.Forms;
|
|
using OpenNest.Geometry;
|
|
using OpenNest.IO;
|
|
using OpenNest.IO.Bom;
|
|
using OpenNest.Tests.Data;
|
|
using static OpenNest.WinForms.Tests.FormTesting;
|
|
using static OpenNest.WinForms.Tests.TestReflection;
|
|
using DrawingSetBrowser = OpenNest.Controls.DrawingSetBrowser;
|
|
|
|
namespace OpenNest.WinForms.Tests.Forms;
|
|
|
|
/// <summary>Drawing Sets > More > Import BOM: a BOM becomes a prefilled set, and nothing is stored unasked.</summary>
|
|
public sealed class ImportBomToSetFormTests : IDisposable
|
|
{
|
|
private const string Server = "http://library.test:8090";
|
|
private static readonly TimeSpan TestTimeout = TimeSpan.FromSeconds(60);
|
|
|
|
private readonly string folder = Path.Combine(Path.GetTempPath(), "bom-to-set-" + Guid.NewGuid().ToString("N"));
|
|
|
|
public ImportBomToSetFormTests()
|
|
{
|
|
Directory.CreateDirectory(folder);
|
|
WriteSquare("PT01", 2);
|
|
WriteSquare("PT02", 3);
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
if (Directory.Exists(folder))
|
|
Directory.Delete(folder, recursive: true);
|
|
}
|
|
|
|
[Fact]
|
|
public void ImportBom_OpensTheEditorPrefilled_AndCancelingItStoresNoSet()
|
|
{
|
|
StaTestThread.Run(
|
|
() =>
|
|
{
|
|
var library = new InMemoryDrawingLibrary();
|
|
// PT01 was imported from this file before; the import reuses it as it is.
|
|
var existing = library.Seed("PT01", "Steel", 0.25, Package("PT01"), customer: "Synthetic Co");
|
|
var sets = new InMemoryDrawingSets();
|
|
var confirmations = new List<string>();
|
|
var editorChecked = false;
|
|
|
|
using var form = new DrawingSetsForm(sets, library, Server);
|
|
var browser = form.Browser;
|
|
browser.ShowMessage = (text, _, _) => throw new Xunit.Sdk.XunitException(text);
|
|
browser.ImportBom = () =>
|
|
{
|
|
using var import = new ImportBomToSetForm(sets, library, Units.Inches, CutType.Laser, "synthetic operator");
|
|
import.ShowMessage = (text, _, _) =>
|
|
{
|
|
confirmations.Add(text);
|
|
return DialogResult.OK;
|
|
};
|
|
import.Show();
|
|
Field<TextBox>(import, "customerBox").Text = "Synthetic Co";
|
|
Field<TextBox>(import, "nameBox").Text = "Job 7";
|
|
Run(import.AnalyzeAsync(Items(), folder, "Job 7 BOM.xlsx"));
|
|
|
|
var grid = Field<DataGridView>(import, "drawingGrid");
|
|
Assert.Equal(
|
|
new[] { "In the library (revision 1)", "New library drawing", "Not imported: no drawing file found" },
|
|
grid.Rows.Cast<DataGridViewRow>().Select(r => r.Cells["libraryColumn"].Value));
|
|
Assert.Contains("no material or thickness", Field<Label>(import, "summaryLabel").Text);
|
|
Assert.Empty(library.Writes);
|
|
|
|
Assert.True(Run(import.CreateSetAsync()));
|
|
return import.Edit;
|
|
};
|
|
browser.EditSet = edit =>
|
|
{
|
|
using var editor = new EditDrawingSetForm(edit, library, Server);
|
|
editor.ShowMessage = (_, _, _) => DialogResult.Yes;
|
|
editor.Show();
|
|
Assert.Equal("Job 7", Field<TextBox>(editor, "nameBox").Text);
|
|
Assert.Equal("Synthetic Co", Field<TextBox>(editor, "customerBox").Text);
|
|
var members = Field<DataGridView>(editor, "memberGrid");
|
|
Assert.Equal(new object[] { "PT01", "PT02" },
|
|
members.Rows.Cast<DataGridViewRow>().Select(r => r.Cells["drawingColumn"].Value));
|
|
Assert.Equal(new[] { (existing.Id, 7), (library.Writes.Single().Id, 3) },
|
|
edit.Members.Select(m => (m.DrawingId, m.Quantity)));
|
|
editorChecked = true;
|
|
editor.Close();
|
|
return null;
|
|
};
|
|
form.Show();
|
|
|
|
Run(browser.ImportBomAsync());
|
|
|
|
Assert.True(editorChecked);
|
|
// One confirmation, naming the one new drawing before it was uploaded.
|
|
Assert.Contains("- PT02 (item 2)", Assert.Single(confirmations));
|
|
Assert.Equal("upload", library.Writes.Single().Kind);
|
|
Assert.Empty(sets.Creates);
|
|
Assert.Empty(sets.Current);
|
|
Assert.Equal("The imported set was not saved.", Field<Label>(browser, "statusLabel").Text);
|
|
},
|
|
TestTimeout,
|
|
"The Import BOM to set test did not complete.");
|
|
}
|
|
|
|
[Fact]
|
|
public void DecliningTheLibraryWrites_OrCanceling_StoresNothing()
|
|
{
|
|
StaTestThread.Run(
|
|
() =>
|
|
{
|
|
var library = new InMemoryDrawingLibrary();
|
|
var sets = new InMemoryDrawingSets();
|
|
using var import = new ImportBomToSetForm(sets, library, Units.Inches, CutType.Laser, "synthetic operator");
|
|
var asked = 0;
|
|
import.ShowMessage = (_, buttons, _) =>
|
|
{
|
|
asked++;
|
|
Assert.Equal(MessageBoxButtons.OKCancel, buttons);
|
|
return DialogResult.Cancel;
|
|
};
|
|
import.Show();
|
|
Run(import.AnalyzeAsync(Items(), folder, "Job 7 BOM.xlsx"));
|
|
Assert.True(import.Plan!.HasWrites);
|
|
|
|
Assert.False(Run(import.CreateSetAsync()));
|
|
Assert.Equal(1, asked);
|
|
Assert.Null(import.Edit);
|
|
Assert.Empty(library.Writes);
|
|
Assert.Empty(library.Current);
|
|
|
|
// A changed customer makes the plan stale until the BOM is read again.
|
|
Field<TextBox>(import, "customerBox").Text = "Another customer";
|
|
Assert.Null(import.Plan);
|
|
Assert.False(Field<Button>(import, "createButton").Enabled);
|
|
|
|
Field<Button>(import, "cancelButton").PerformClick();
|
|
Assert.Equal(DialogResult.Cancel, import.DialogResult);
|
|
Assert.Empty(library.Writes);
|
|
Assert.Empty(sets.Creates);
|
|
},
|
|
TestTimeout,
|
|
"The declined Import BOM test did not complete.");
|
|
}
|
|
|
|
[Fact]
|
|
public void ImportBom_IsInTheMoreMenu_WithoutASelectedSet_AndNotInThePicker()
|
|
{
|
|
StaTestThread.Run(
|
|
() =>
|
|
{
|
|
var library = new InMemoryDrawingLibrary();
|
|
var sets = new InMemoryDrawingSets();
|
|
using var form = new DrawingSetsForm(sets, library, Server);
|
|
form.Show();
|
|
var browser = form.Browser;
|
|
PumpUntil(() => sets.Queries.Count == 1, "the set list");
|
|
PumpUntil(() => Field<Button>(browser, "moreButton").Enabled, "the More button");
|
|
|
|
var item = Field<ToolStripMenuItem>(browser, "importBomMenuItem");
|
|
Assert.Null(browser.SelectedSet);
|
|
Assert.True(item.Enabled);
|
|
Assert.Same(item, Field<ContextMenuStrip>(browser, "moreMenu").Items.Cast<ToolStripItem>().Last());
|
|
|
|
using var picker = new ChooseDrawingSetForm(sets, library, Server);
|
|
picker.Show();
|
|
var pickBrowser = Field<DrawingSetBrowser>(picker, "browser");
|
|
Assert.False(Field<ToolStripMenuItem>(pickBrowser, "importBomMenuItem").Enabled);
|
|
Assert.Null(Field<DataGridView>(pickBrowser, "setGrid").ContextMenuStrip);
|
|
},
|
|
TestTimeout,
|
|
"The Import BOM menu test did not complete.");
|
|
}
|
|
|
|
private static List<BomItem> Items() => new()
|
|
{
|
|
new BomItem { ItemNum = 1, FileName = "PT01", Qty = 3, Material = "Steel", Thickness = 0.25 },
|
|
new BomItem { ItemNum = 2, FileName = "PT02", Qty = 3 },
|
|
new BomItem { ItemNum = 3, FileName = "MISSING", Qty = 1, Material = "Steel", Thickness = 0.25 },
|
|
new BomItem { ItemNum = 4, FileName = "PT01.dxf", Qty = 4, Material = "steel", Thickness = 0.25 },
|
|
};
|
|
|
|
private byte[] Package(string name)
|
|
{
|
|
var rows = BomImportRows.Build(new List<BomItem> { new() { FileName = name, Qty = 1 } }, folder);
|
|
return BomSetDrawings.Build(rows, Units.Inches).Drawings.Single().Package;
|
|
}
|
|
|
|
private void WriteSquare(string name, double size)
|
|
{
|
|
var shape = new Shape();
|
|
shape.Entities.Add(new Line(new Vector(0, 0), new Vector(size, 0)));
|
|
shape.Entities.Add(new Line(new Vector(size, 0), new Vector(size, size)));
|
|
shape.Entities.Add(new Line(new Vector(size, size), new Vector(0, size)));
|
|
shape.Entities.Add(new Line(new Vector(0, size), new Vector(0, 0)));
|
|
Dxf.ExportProgram(ConvertGeometry.ToProgram(shape), Path.Combine(folder, name + ".dxf"));
|
|
}
|
|
|
|
private static void Run(Task task) => PumpUntil(() => task.IsCompleted, "the operation to finish");
|
|
|
|
private static T Run<T>(Task<T> task)
|
|
{
|
|
PumpUntil(() => task.IsCompleted, "the operation to finish");
|
|
return task.GetAwaiter().GetResult();
|
|
}
|
|
}
|