mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-10-31 19:11:53 -04:00
Add OpenNest.Desktop (net8.0), the toolkit-neutral layer the WinForms app and OpenNest.Avalonia will share, and OpenNest.Desktop.Tests with a guard that the library references no WinForms/WindowsDesktop, System.Drawing.Common or Avalonia assembly, project setting or (transitive) package. Both desktop front ends reference it; OpenNest.Avalonia joins OpenNest.sln and the new tests join the Linux CI matrix. No code moves yet. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
82 lines
3.0 KiB
C#
82 lines
3.0 KiB
C#
using System.Reflection;
|
|
using System.Text.Json;
|
|
using System.Xml.Linq;
|
|
|
|
namespace OpenNest.Desktop.Tests;
|
|
|
|
/// <summary>
|
|
/// OpenNest.Desktop is shared by the WinForms and Avalonia front ends, so it must stay free of
|
|
/// any UI toolkit: no WinForms/WindowsDesktop framework, System.Drawing.Common or Avalonia.
|
|
/// </summary>
|
|
public class DesktopDependencyTests
|
|
{
|
|
private static readonly string[] ForbiddenPrefixes =
|
|
[
|
|
"System.Windows.Forms",
|
|
"Microsoft.WindowsDesktop",
|
|
"WindowsBase",
|
|
"PresentationCore",
|
|
"PresentationFramework",
|
|
"System.Drawing.Common",
|
|
"Avalonia",
|
|
];
|
|
|
|
[Fact]
|
|
public void DesktopAssembly_ReferencesNoUiToolkit()
|
|
{
|
|
var assembly = Assembly.Load(new AssemblyName("OpenNest.Desktop"));
|
|
var references = assembly.GetReferencedAssemblies().Select(a => a.Name!);
|
|
|
|
Assert.Empty(references.Where(IsForbidden));
|
|
}
|
|
|
|
[Fact]
|
|
public void DesktopProject_TargetsPlainNet8WithoutUiFrameworks()
|
|
{
|
|
var project = XDocument.Load(Path.Combine(DesktopProjectDirectory(), "OpenNest.Desktop.csproj"));
|
|
var elements = project.Descendants().ToList();
|
|
|
|
var targets = elements
|
|
.Where(e => e.Name.LocalName is "TargetFramework" or "TargetFrameworks")
|
|
.SelectMany(e => e.Value.Split(';', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries))
|
|
.ToList();
|
|
Assert.Equal(["net8.0"], targets);
|
|
|
|
Assert.DoesNotContain(elements, e =>
|
|
e.Name.LocalName is "UseWindowsForms" or "UseWPF" or "UseWindowsDesktop"
|
|
&& e.Value.Trim().Equals("true", StringComparison.OrdinalIgnoreCase));
|
|
Assert.DoesNotContain(elements, e => e.Name.LocalName == "FrameworkReference");
|
|
|
|
var packages = elements
|
|
.Where(e => e.Name.LocalName == "PackageReference")
|
|
.Select(e => (string?)e.Attribute("Include") ?? string.Empty);
|
|
Assert.Empty(packages.Where(IsForbidden));
|
|
}
|
|
|
|
[Fact]
|
|
public void DesktopProject_RestoresNoUiToolkitPackagesTransitively()
|
|
{
|
|
var assetsPath = Path.Combine(DesktopProjectDirectory(), "obj", "project.assets.json");
|
|
Assert.True(File.Exists(assetsPath), $"Restore output not found: {assetsPath}");
|
|
|
|
using var assets = JsonDocument.Parse(File.ReadAllText(assetsPath));
|
|
var libraries = assets.RootElement.GetProperty("libraries").EnumerateObject()
|
|
.Select(library => library.Name.Split('/')[0]);
|
|
|
|
Assert.Empty(libraries.Where(IsForbidden));
|
|
}
|
|
|
|
private static bool IsForbidden(string name) =>
|
|
ForbiddenPrefixes.Any(prefix => name.StartsWith(prefix, StringComparison.OrdinalIgnoreCase));
|
|
|
|
private static string DesktopProjectDirectory()
|
|
{
|
|
var directory = new DirectoryInfo(AppContext.BaseDirectory);
|
|
while (directory != null && !File.Exists(Path.Combine(directory.FullName, "OpenNest.sln")))
|
|
directory = directory.Parent;
|
|
|
|
Assert.NotNull(directory);
|
|
return Path.Combine(directory.FullName, "OpenNest.Desktop");
|
|
}
|
|
}
|