From c3697c60b9bbb777ca550c0ae2691151a09ed2a8 Mon Sep 17 00:00:00 2001 From: kalen-releasedgroup Date: Thu, 23 Apr 2026 14:05:38 +1000 Subject: [PATCH 1/2] Scaffold TestMining.Platform project skeleton --- Directory.Build.props | 26 +-- Symphony.slnx | 44 ++++-- .../TestMining.Platform.Analysis.csproj | 11 ++ .../ApplicationAssemblyMarker.cs | 5 + .../TestMining.Platform.Application.csproj | 11 ++ .../TestMining.Platform.Artefacts.csproj | 11 ++ .../TestMining.Platform.Contracts.csproj | 6 + .../CoreAssemblyMarker.cs | 5 + .../TestMining.Platform.Core.csproj | 7 + .../GenerationAssemblyMarker.cs | 5 + .../TestMining.Platform.Generation.csproj | 11 ++ .../TestMining.Platform.Healing.csproj | 11 ++ .../HostAssemblyMarker.cs | 5 + src/TestMining.Platform.Host/Program.cs | 10 ++ .../TestMining.Platform.Host.csproj | 18 +++ .../TestMining.Platform.Persistence.csproj | 11 ++ .../TestMining.Platform.Recorder.csproj | 10 ++ src/TestMining.Platform.Recorder/recorder.js | 2 + .../TestMining.Platform.Recording.csproj | 12 ++ .../TestMining.Platform.Replay.csproj | 11 ++ .../ApplicationProjectSmokeTests.cs | 10 ++ ...stMining.Platform.Application.Tests.csproj | 22 +++ .../CoreProjectSmokeTests.cs | 10 ++ .../TestMining.Platform.Core.Tests.csproj | 22 +++ .../E2EProjectSmokeTests.cs | 11 ++ .../TestMining.Platform.E2E.Tests.csproj | 23 +++ .../FixturesAssemblyMarker.cs | 5 + .../TestMining.Platform.Fixtures.csproj | 6 + .../GenerationProjectSmokeTests.cs | 10 ++ ...TestMining.Platform.Generator.Tests.csproj | 22 +++ .../PlatformSolutionConformanceTests.cs | 149 ++++++++++++++++++ ...stMining.Platform.Integration.Tests.csproj | 22 +++ 32 files changed, 520 insertions(+), 24 deletions(-) create mode 100644 src/TestMining.Platform.Analysis/TestMining.Platform.Analysis.csproj create mode 100644 src/TestMining.Platform.Application/ApplicationAssemblyMarker.cs create mode 100644 src/TestMining.Platform.Application/TestMining.Platform.Application.csproj create mode 100644 src/TestMining.Platform.Artefacts/TestMining.Platform.Artefacts.csproj create mode 100644 src/TestMining.Platform.Contracts/TestMining.Platform.Contracts.csproj create mode 100644 src/TestMining.Platform.Core/CoreAssemblyMarker.cs create mode 100644 src/TestMining.Platform.Core/TestMining.Platform.Core.csproj create mode 100644 src/TestMining.Platform.Generation/GenerationAssemblyMarker.cs create mode 100644 src/TestMining.Platform.Generation/TestMining.Platform.Generation.csproj create mode 100644 src/TestMining.Platform.Healing/TestMining.Platform.Healing.csproj create mode 100644 src/TestMining.Platform.Host/HostAssemblyMarker.cs create mode 100644 src/TestMining.Platform.Host/Program.cs create mode 100644 src/TestMining.Platform.Host/TestMining.Platform.Host.csproj create mode 100644 src/TestMining.Platform.Persistence/TestMining.Platform.Persistence.csproj create mode 100644 src/TestMining.Platform.Recorder/TestMining.Platform.Recorder.csproj create mode 100644 src/TestMining.Platform.Recorder/recorder.js create mode 100644 src/TestMining.Platform.Recording/TestMining.Platform.Recording.csproj create mode 100644 src/TestMining.Platform.Replay/TestMining.Platform.Replay.csproj create mode 100644 tests/TestMining.Platform.Application.Tests/ApplicationProjectSmokeTests.cs create mode 100644 tests/TestMining.Platform.Application.Tests/TestMining.Platform.Application.Tests.csproj create mode 100644 tests/TestMining.Platform.Core.Tests/CoreProjectSmokeTests.cs create mode 100644 tests/TestMining.Platform.Core.Tests/TestMining.Platform.Core.Tests.csproj create mode 100644 tests/TestMining.Platform.E2E.Tests/E2EProjectSmokeTests.cs create mode 100644 tests/TestMining.Platform.E2E.Tests/TestMining.Platform.E2E.Tests.csproj create mode 100644 tests/TestMining.Platform.Fixtures/FixturesAssemblyMarker.cs create mode 100644 tests/TestMining.Platform.Fixtures/TestMining.Platform.Fixtures.csproj create mode 100644 tests/TestMining.Platform.Generator.Tests/GenerationProjectSmokeTests.cs create mode 100644 tests/TestMining.Platform.Generator.Tests/TestMining.Platform.Generator.Tests.csproj create mode 100644 tests/TestMining.Platform.Integration.Tests/PlatformSolutionConformanceTests.cs create mode 100644 tests/TestMining.Platform.Integration.Tests/TestMining.Platform.Integration.Tests.csproj diff --git a/Directory.Build.props b/Directory.Build.props index 2fb3364..cf8b26f 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,8 +1,8 @@ - - - ReleasedGroup - ReleasedGroup - Symphony + + + ReleasedGroup + ReleasedGroup + Symphony https://github.com/ReleasedGroup/Symphony 0.1.0 dev @@ -10,9 +10,13 @@ $(SymphonyVersionSuffix) $(VersionPrefix)-$(VersionSuffix) $(VersionPrefix) - $(VersionPrefix).0 - $(VersionPrefix).0 - $(Version) - false - - + $(VersionPrefix).0 + $(VersionPrefix).0 + $(Version) + false + enable + true + true + latest-recommended + + diff --git a/Symphony.slnx b/Symphony.slnx index 5e01600..1720320 100644 --- a/Symphony.slnx +++ b/Symphony.slnx @@ -1,15 +1,33 @@ - - - - - - - + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + + + + + + + diff --git a/src/TestMining.Platform.Analysis/TestMining.Platform.Analysis.csproj b/src/TestMining.Platform.Analysis/TestMining.Platform.Analysis.csproj new file mode 100644 index 0000000..e28032c --- /dev/null +++ b/src/TestMining.Platform.Analysis/TestMining.Platform.Analysis.csproj @@ -0,0 +1,11 @@ + + + net10.0 + enable + + + + + + + diff --git a/src/TestMining.Platform.Application/ApplicationAssemblyMarker.cs b/src/TestMining.Platform.Application/ApplicationAssemblyMarker.cs new file mode 100644 index 0000000..151576f --- /dev/null +++ b/src/TestMining.Platform.Application/ApplicationAssemblyMarker.cs @@ -0,0 +1,5 @@ +namespace TestMining.Platform.Application; + +public static class ApplicationAssemblyMarker +{ +} diff --git a/src/TestMining.Platform.Application/TestMining.Platform.Application.csproj b/src/TestMining.Platform.Application/TestMining.Platform.Application.csproj new file mode 100644 index 0000000..2fbf9ed --- /dev/null +++ b/src/TestMining.Platform.Application/TestMining.Platform.Application.csproj @@ -0,0 +1,11 @@ + + + net10.0 + enable + + + + + + + diff --git a/src/TestMining.Platform.Artefacts/TestMining.Platform.Artefacts.csproj b/src/TestMining.Platform.Artefacts/TestMining.Platform.Artefacts.csproj new file mode 100644 index 0000000..e28032c --- /dev/null +++ b/src/TestMining.Platform.Artefacts/TestMining.Platform.Artefacts.csproj @@ -0,0 +1,11 @@ + + + net10.0 + enable + + + + + + + diff --git a/src/TestMining.Platform.Contracts/TestMining.Platform.Contracts.csproj b/src/TestMining.Platform.Contracts/TestMining.Platform.Contracts.csproj new file mode 100644 index 0000000..6948928 --- /dev/null +++ b/src/TestMining.Platform.Contracts/TestMining.Platform.Contracts.csproj @@ -0,0 +1,6 @@ + + + net10.0 + enable + + diff --git a/src/TestMining.Platform.Core/CoreAssemblyMarker.cs b/src/TestMining.Platform.Core/CoreAssemblyMarker.cs new file mode 100644 index 0000000..a22be29 --- /dev/null +++ b/src/TestMining.Platform.Core/CoreAssemblyMarker.cs @@ -0,0 +1,5 @@ +namespace TestMining.Platform.Core; + +public static class CoreAssemblyMarker +{ +} diff --git a/src/TestMining.Platform.Core/TestMining.Platform.Core.csproj b/src/TestMining.Platform.Core/TestMining.Platform.Core.csproj new file mode 100644 index 0000000..3f308b0 --- /dev/null +++ b/src/TestMining.Platform.Core/TestMining.Platform.Core.csproj @@ -0,0 +1,7 @@ + + + net10.0 + enable + true + + diff --git a/src/TestMining.Platform.Generation/GenerationAssemblyMarker.cs b/src/TestMining.Platform.Generation/GenerationAssemblyMarker.cs new file mode 100644 index 0000000..788bbbd --- /dev/null +++ b/src/TestMining.Platform.Generation/GenerationAssemblyMarker.cs @@ -0,0 +1,5 @@ +namespace TestMining.Platform.Generation; + +public static class GenerationAssemblyMarker +{ +} diff --git a/src/TestMining.Platform.Generation/TestMining.Platform.Generation.csproj b/src/TestMining.Platform.Generation/TestMining.Platform.Generation.csproj new file mode 100644 index 0000000..e28032c --- /dev/null +++ b/src/TestMining.Platform.Generation/TestMining.Platform.Generation.csproj @@ -0,0 +1,11 @@ + + + net10.0 + enable + + + + + + + diff --git a/src/TestMining.Platform.Healing/TestMining.Platform.Healing.csproj b/src/TestMining.Platform.Healing/TestMining.Platform.Healing.csproj new file mode 100644 index 0000000..e28032c --- /dev/null +++ b/src/TestMining.Platform.Healing/TestMining.Platform.Healing.csproj @@ -0,0 +1,11 @@ + + + net10.0 + enable + + + + + + + diff --git a/src/TestMining.Platform.Host/HostAssemblyMarker.cs b/src/TestMining.Platform.Host/HostAssemblyMarker.cs new file mode 100644 index 0000000..14526ee --- /dev/null +++ b/src/TestMining.Platform.Host/HostAssemblyMarker.cs @@ -0,0 +1,5 @@ +namespace TestMining.Platform.Host; + +public static class HostAssemblyMarker +{ +} diff --git a/src/TestMining.Platform.Host/Program.cs b/src/TestMining.Platform.Host/Program.cs new file mode 100644 index 0000000..927576d --- /dev/null +++ b/src/TestMining.Platform.Host/Program.cs @@ -0,0 +1,10 @@ +var builder = WebApplication.CreateBuilder(args); + +builder.Services.AddRazorPages(); +builder.Services.AddServerSideBlazor(); + +var app = builder.Build(); + +app.MapGet("/", () => Results.Ok("TestMining Platform Host")); + +app.Run(); diff --git a/src/TestMining.Platform.Host/TestMining.Platform.Host.csproj b/src/TestMining.Platform.Host/TestMining.Platform.Host.csproj new file mode 100644 index 0000000..96be8aa --- /dev/null +++ b/src/TestMining.Platform.Host/TestMining.Platform.Host.csproj @@ -0,0 +1,18 @@ + + + net10.0 + enable + + + + + + + + + + + + + + diff --git a/src/TestMining.Platform.Persistence/TestMining.Platform.Persistence.csproj b/src/TestMining.Platform.Persistence/TestMining.Platform.Persistence.csproj new file mode 100644 index 0000000..e28032c --- /dev/null +++ b/src/TestMining.Platform.Persistence/TestMining.Platform.Persistence.csproj @@ -0,0 +1,11 @@ + + + net10.0 + enable + + + + + + + diff --git a/src/TestMining.Platform.Recorder/TestMining.Platform.Recorder.csproj b/src/TestMining.Platform.Recorder/TestMining.Platform.Recorder.csproj new file mode 100644 index 0000000..f2b26ee --- /dev/null +++ b/src/TestMining.Platform.Recorder/TestMining.Platform.Recorder.csproj @@ -0,0 +1,10 @@ + + + net10.0 + enable + + + + + + diff --git a/src/TestMining.Platform.Recorder/recorder.js b/src/TestMining.Platform.Recorder/recorder.js new file mode 100644 index 0000000..627ede8 --- /dev/null +++ b/src/TestMining.Platform.Recorder/recorder.js @@ -0,0 +1,2 @@ +// Placeholder recorder asset for the initial platform scaffold. +// Future recorder builds should keep this versioned and deterministic. diff --git a/src/TestMining.Platform.Recording/TestMining.Platform.Recording.csproj b/src/TestMining.Platform.Recording/TestMining.Platform.Recording.csproj new file mode 100644 index 0000000..bfaa5b8 --- /dev/null +++ b/src/TestMining.Platform.Recording/TestMining.Platform.Recording.csproj @@ -0,0 +1,12 @@ + + + net10.0 + enable + + + + + + + + diff --git a/src/TestMining.Platform.Replay/TestMining.Platform.Replay.csproj b/src/TestMining.Platform.Replay/TestMining.Platform.Replay.csproj new file mode 100644 index 0000000..e28032c --- /dev/null +++ b/src/TestMining.Platform.Replay/TestMining.Platform.Replay.csproj @@ -0,0 +1,11 @@ + + + net10.0 + enable + + + + + + + diff --git a/tests/TestMining.Platform.Application.Tests/ApplicationProjectSmokeTests.cs b/tests/TestMining.Platform.Application.Tests/ApplicationProjectSmokeTests.cs new file mode 100644 index 0000000..56af59f --- /dev/null +++ b/tests/TestMining.Platform.Application.Tests/ApplicationProjectSmokeTests.cs @@ -0,0 +1,10 @@ +namespace TestMining.Platform.Application.Tests; + +public sealed class ApplicationProjectSmokeTests +{ + [Fact(DisplayName = "Section 22.2 keeps the application project wired into the scaffolded test suite")] + public void ApplicationProjectReferenceIsPresent() + { + Assert.Equal("TestMining.Platform.Application", typeof(TestMining.Platform.Application.ApplicationAssemblyMarker).Assembly.GetName().Name); + } +} diff --git a/tests/TestMining.Platform.Application.Tests/TestMining.Platform.Application.Tests.csproj b/tests/TestMining.Platform.Application.Tests/TestMining.Platform.Application.Tests.csproj new file mode 100644 index 0000000..93179ca --- /dev/null +++ b/tests/TestMining.Platform.Application.Tests/TestMining.Platform.Application.Tests.csproj @@ -0,0 +1,22 @@ + + + net10.0 + enable + false + + + + + + + + + + + + + + + + + diff --git a/tests/TestMining.Platform.Core.Tests/CoreProjectSmokeTests.cs b/tests/TestMining.Platform.Core.Tests/CoreProjectSmokeTests.cs new file mode 100644 index 0000000..d1d1ef2 --- /dev/null +++ b/tests/TestMining.Platform.Core.Tests/CoreProjectSmokeTests.cs @@ -0,0 +1,10 @@ +namespace TestMining.Platform.Core.Tests; + +public sealed class CoreProjectSmokeTests +{ + [Fact(DisplayName = "Section 22.2 keeps the core project wired into the scaffolded test suite")] + public void CoreProjectReferenceIsPresent() + { + Assert.Equal("TestMining.Platform.Core", typeof(TestMining.Platform.Core.CoreAssemblyMarker).Assembly.GetName().Name); + } +} diff --git a/tests/TestMining.Platform.Core.Tests/TestMining.Platform.Core.Tests.csproj b/tests/TestMining.Platform.Core.Tests/TestMining.Platform.Core.Tests.csproj new file mode 100644 index 0000000..cbbcf02 --- /dev/null +++ b/tests/TestMining.Platform.Core.Tests/TestMining.Platform.Core.Tests.csproj @@ -0,0 +1,22 @@ + + + net10.0 + enable + false + + + + + + + + + + + + + + + + + diff --git a/tests/TestMining.Platform.E2E.Tests/E2EProjectSmokeTests.cs b/tests/TestMining.Platform.E2E.Tests/E2EProjectSmokeTests.cs new file mode 100644 index 0000000..f2a8d47 --- /dev/null +++ b/tests/TestMining.Platform.E2E.Tests/E2EProjectSmokeTests.cs @@ -0,0 +1,11 @@ +namespace TestMining.Platform.E2E.Tests; + +public sealed class E2EProjectSmokeTests +{ + [Fact(DisplayName = "Section 22.2 keeps the host and fixtures projects wired into the scaffolded E2E suite")] + public void HostAndFixturesProjectReferencesArePresent() + { + Assert.Equal("TestMining.Platform.Host", typeof(TestMining.Platform.Host.HostAssemblyMarker).Assembly.GetName().Name); + Assert.Equal("TestMining.Platform.Fixtures", typeof(TestMining.Platform.Fixtures.FixturesAssemblyMarker).Assembly.GetName().Name); + } +} diff --git a/tests/TestMining.Platform.E2E.Tests/TestMining.Platform.E2E.Tests.csproj b/tests/TestMining.Platform.E2E.Tests/TestMining.Platform.E2E.Tests.csproj new file mode 100644 index 0000000..d7978fb --- /dev/null +++ b/tests/TestMining.Platform.E2E.Tests/TestMining.Platform.E2E.Tests.csproj @@ -0,0 +1,23 @@ + + + net10.0 + enable + false + + + + + + + + + + + + + + + + + + diff --git a/tests/TestMining.Platform.Fixtures/FixturesAssemblyMarker.cs b/tests/TestMining.Platform.Fixtures/FixturesAssemblyMarker.cs new file mode 100644 index 0000000..e02055a --- /dev/null +++ b/tests/TestMining.Platform.Fixtures/FixturesAssemblyMarker.cs @@ -0,0 +1,5 @@ +namespace TestMining.Platform.Fixtures; + +public static class FixturesAssemblyMarker +{ +} diff --git a/tests/TestMining.Platform.Fixtures/TestMining.Platform.Fixtures.csproj b/tests/TestMining.Platform.Fixtures/TestMining.Platform.Fixtures.csproj new file mode 100644 index 0000000..6948928 --- /dev/null +++ b/tests/TestMining.Platform.Fixtures/TestMining.Platform.Fixtures.csproj @@ -0,0 +1,6 @@ + + + net10.0 + enable + + diff --git a/tests/TestMining.Platform.Generator.Tests/GenerationProjectSmokeTests.cs b/tests/TestMining.Platform.Generator.Tests/GenerationProjectSmokeTests.cs new file mode 100644 index 0000000..624cddf --- /dev/null +++ b/tests/TestMining.Platform.Generator.Tests/GenerationProjectSmokeTests.cs @@ -0,0 +1,10 @@ +namespace TestMining.Platform.Generator.Tests; + +public sealed class GenerationProjectSmokeTests +{ + [Fact(DisplayName = "Section 22.2 keeps the generation project wired into the scaffolded test suite")] + public void GenerationProjectReferenceIsPresent() + { + Assert.Equal("TestMining.Platform.Generation", typeof(TestMining.Platform.Generation.GenerationAssemblyMarker).Assembly.GetName().Name); + } +} diff --git a/tests/TestMining.Platform.Generator.Tests/TestMining.Platform.Generator.Tests.csproj b/tests/TestMining.Platform.Generator.Tests/TestMining.Platform.Generator.Tests.csproj new file mode 100644 index 0000000..c929456 --- /dev/null +++ b/tests/TestMining.Platform.Generator.Tests/TestMining.Platform.Generator.Tests.csproj @@ -0,0 +1,22 @@ + + + net10.0 + enable + false + + + + + + + + + + + + + + + + + diff --git a/tests/TestMining.Platform.Integration.Tests/PlatformSolutionConformanceTests.cs b/tests/TestMining.Platform.Integration.Tests/PlatformSolutionConformanceTests.cs new file mode 100644 index 0000000..c14f57d --- /dev/null +++ b/tests/TestMining.Platform.Integration.Tests/PlatformSolutionConformanceTests.cs @@ -0,0 +1,149 @@ +using System.Xml.Linq; + +namespace TestMining.Platform.Integration.Tests; + +public sealed class PlatformSolutionConformanceTests +{ + private static readonly string RepositoryRoot = FindRepositoryRoot(); + + [Fact(DisplayName = "Sections 17 and 22.1 require the TestMining.Platform vertical slice to exist as a distinct scaffold")] + public void PlatformProjectsExistInTheRepositorySolution() + { + var solutionDocument = XDocument.Load(Path.Combine(RepositoryRoot, "Symphony.slnx")); + var projectPaths = solutionDocument + .Descendants("Project") + .Select(node => node.Attribute("Path")?.Value) + .Where(path => path is not null && path.Contains("TestMining.Platform", StringComparison.Ordinal)) + .OrderBy(path => path, StringComparer.Ordinal) + .ToArray(); + + var expectedPaths = GetExpectedProjectPaths() + .OrderBy(path => path, StringComparer.Ordinal) + .ToArray(); + + Assert.Equal(expectedPaths, projectPaths); + } + + [Fact(DisplayName = "Sections 17, 22.2, and 23.1 item 6 keep platform project references aligned with the intended boundaries")] + public void PlatformProjectsUseTheExpectedReferenceGraph() + { + var expectedReferenceGraph = new Dictionary(StringComparer.Ordinal) + { + ["src/TestMining.Platform.Application/TestMining.Platform.Application.csproj"] = + [ + "src/TestMining.Platform.Contracts/TestMining.Platform.Contracts.csproj", + "src/TestMining.Platform.Core/TestMining.Platform.Core.csproj", + ], + ["src/TestMining.Platform.Analysis/TestMining.Platform.Analysis.csproj"] = + [ + "src/TestMining.Platform.Application/TestMining.Platform.Application.csproj", + "src/TestMining.Platform.Core/TestMining.Platform.Core.csproj", + ], + ["src/TestMining.Platform.Artefacts/TestMining.Platform.Artefacts.csproj"] = + [ + "src/TestMining.Platform.Application/TestMining.Platform.Application.csproj", + "src/TestMining.Platform.Core/TestMining.Platform.Core.csproj", + ], + ["src/TestMining.Platform.Contracts/TestMining.Platform.Contracts.csproj"] = [], + ["src/TestMining.Platform.Core/TestMining.Platform.Core.csproj"] = [], + ["src/TestMining.Platform.Generation/TestMining.Platform.Generation.csproj"] = + [ + "src/TestMining.Platform.Application/TestMining.Platform.Application.csproj", + "src/TestMining.Platform.Core/TestMining.Platform.Core.csproj", + ], + ["src/TestMining.Platform.Healing/TestMining.Platform.Healing.csproj"] = + [ + "src/TestMining.Platform.Application/TestMining.Platform.Application.csproj", + "src/TestMining.Platform.Core/TestMining.Platform.Core.csproj", + ], + ["src/TestMining.Platform.Host/TestMining.Platform.Host.csproj"] = + [ + "src/TestMining.Platform.Analysis/TestMining.Platform.Analysis.csproj", + "src/TestMining.Platform.Application/TestMining.Platform.Application.csproj", + "src/TestMining.Platform.Artefacts/TestMining.Platform.Artefacts.csproj", + "src/TestMining.Platform.Contracts/TestMining.Platform.Contracts.csproj", + "src/TestMining.Platform.Generation/TestMining.Platform.Generation.csproj", + "src/TestMining.Platform.Healing/TestMining.Platform.Healing.csproj", + "src/TestMining.Platform.Persistence/TestMining.Platform.Persistence.csproj", + "src/TestMining.Platform.Recording/TestMining.Platform.Recording.csproj", + "src/TestMining.Platform.Replay/TestMining.Platform.Replay.csproj", + ], + ["src/TestMining.Platform.Persistence/TestMining.Platform.Persistence.csproj"] = + [ + "src/TestMining.Platform.Application/TestMining.Platform.Application.csproj", + "src/TestMining.Platform.Core/TestMining.Platform.Core.csproj", + ], + ["src/TestMining.Platform.Recorder/TestMining.Platform.Recorder.csproj"] = [], + ["src/TestMining.Platform.Recording/TestMining.Platform.Recording.csproj"] = + [ + "src/TestMining.Platform.Application/TestMining.Platform.Application.csproj", + "src/TestMining.Platform.Core/TestMining.Platform.Core.csproj", + "src/TestMining.Platform.Recorder/TestMining.Platform.Recorder.csproj", + ], + ["src/TestMining.Platform.Replay/TestMining.Platform.Replay.csproj"] = + [ + "src/TestMining.Platform.Application/TestMining.Platform.Application.csproj", + "src/TestMining.Platform.Core/TestMining.Platform.Core.csproj", + ], + }; + + foreach (var (projectPath, expectedReferences) in expectedReferenceGraph) + { + var projectDocument = XDocument.Load(Path.Combine(RepositoryRoot, projectPath)); + var projectDirectory = Path.GetDirectoryName(projectPath) + ?? throw new InvalidOperationException($"Unable to resolve a directory for '{projectPath}'."); + + var actualReferences = projectDocument + .Descendants("ProjectReference") + .Select(node => node.Attribute("Include")?.Value) + .Where(value => !string.IsNullOrWhiteSpace(value)) + .Select(value => NormalizePath(Path.GetRelativePath( + RepositoryRoot, + Path.GetFullPath(Path.Combine(RepositoryRoot, projectDirectory, value!))))) + .OrderBy(path => path, StringComparer.Ordinal) + .ToArray(); + + var expectedNormalizedReferences = expectedReferences + .OrderBy(path => path, StringComparer.Ordinal) + .ToArray(); + + Assert.Equal(expectedNormalizedReferences, actualReferences); + } + } + + private static string[] GetExpectedProjectPaths() => + [ + "src/TestMining.Platform.Analysis/TestMining.Platform.Analysis.csproj", + "src/TestMining.Platform.Application/TestMining.Platform.Application.csproj", + "src/TestMining.Platform.Artefacts/TestMining.Platform.Artefacts.csproj", + "src/TestMining.Platform.Contracts/TestMining.Platform.Contracts.csproj", + "src/TestMining.Platform.Core/TestMining.Platform.Core.csproj", + "src/TestMining.Platform.Generation/TestMining.Platform.Generation.csproj", + "src/TestMining.Platform.Healing/TestMining.Platform.Healing.csproj", + "src/TestMining.Platform.Host/TestMining.Platform.Host.csproj", + "src/TestMining.Platform.Persistence/TestMining.Platform.Persistence.csproj", + "src/TestMining.Platform.Recorder/TestMining.Platform.Recorder.csproj", + "src/TestMining.Platform.Recording/TestMining.Platform.Recording.csproj", + "src/TestMining.Platform.Replay/TestMining.Platform.Replay.csproj", + "tests/TestMining.Platform.Application.Tests/TestMining.Platform.Application.Tests.csproj", + "tests/TestMining.Platform.Core.Tests/TestMining.Platform.Core.Tests.csproj", + "tests/TestMining.Platform.E2E.Tests/TestMining.Platform.E2E.Tests.csproj", + "tests/TestMining.Platform.Fixtures/TestMining.Platform.Fixtures.csproj", + "tests/TestMining.Platform.Generator.Tests/TestMining.Platform.Generator.Tests.csproj", + "tests/TestMining.Platform.Integration.Tests/TestMining.Platform.Integration.Tests.csproj", + ]; + + private static string FindRepositoryRoot() + { + var current = new DirectoryInfo(AppContext.BaseDirectory); + + while (current is not null && !File.Exists(Path.Combine(current.FullName, "AGENTS.md"))) + { + current = current.Parent; + } + + return current?.FullName ?? throw new InvalidOperationException("Unable to locate the repository root."); + } + + private static string NormalizePath(string path) => path.Replace('\\', '/'); +} diff --git a/tests/TestMining.Platform.Integration.Tests/TestMining.Platform.Integration.Tests.csproj b/tests/TestMining.Platform.Integration.Tests/TestMining.Platform.Integration.Tests.csproj new file mode 100644 index 0000000..2e612d6 --- /dev/null +++ b/tests/TestMining.Platform.Integration.Tests/TestMining.Platform.Integration.Tests.csproj @@ -0,0 +1,22 @@ + + + net10.0 + enable + false + + + + + + + + + + + + + + + + + From d2bef7697dfe55e4b0b78d7998d8b48562206f1b Mon Sep 17 00:00:00 2001 From: kalen-releasedgroup Date: Thu, 23 Apr 2026 15:42:47 +1000 Subject: [PATCH 2/2] Add platform build convention conformance coverage --- .../PlatformSolutionConformanceTests.cs | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/tests/TestMining.Platform.Integration.Tests/PlatformSolutionConformanceTests.cs b/tests/TestMining.Platform.Integration.Tests/PlatformSolutionConformanceTests.cs index c14f57d..89a0dcb 100644 --- a/tests/TestMining.Platform.Integration.Tests/PlatformSolutionConformanceTests.cs +++ b/tests/TestMining.Platform.Integration.Tests/PlatformSolutionConformanceTests.cs @@ -111,6 +111,26 @@ public void PlatformProjectsUseTheExpectedReferenceGraph() } } + [Fact(DisplayName = "Sections 22.1 and 22.2 require shared nullable, deterministic, and analyzer conventions across the platform scaffold")] + public void PlatformProjectsInheritSharedRepositoryBuildConventions() + { + var directoryBuildProps = XDocument.Load(Path.Combine(RepositoryRoot, "Directory.Build.props")); + + Assert.Equal("enable", GetProjectPropertyValue(directoryBuildProps, "Nullable")); + Assert.Equal("true", GetProjectPropertyValue(directoryBuildProps, "Deterministic")); + Assert.Equal("true", GetProjectPropertyValue(directoryBuildProps, "EnableNETAnalyzers")); + Assert.Equal("latest-recommended", GetProjectPropertyValue(directoryBuildProps, "AnalysisLevel")); + + foreach (var projectPath in GetExpectedProjectPaths()) + { + var projectDocument = XDocument.Load(Path.Combine(RepositoryRoot, projectPath)); + + Assert.NotEqual("disable", GetProjectPropertyValue(projectDocument, "Nullable")); + Assert.NotEqual("false", GetProjectPropertyValue(projectDocument, "Deterministic")); + Assert.NotEqual("false", GetProjectPropertyValue(projectDocument, "EnableNETAnalyzers")); + } + } + private static string[] GetExpectedProjectPaths() => [ "src/TestMining.Platform.Analysis/TestMining.Platform.Analysis.csproj", @@ -145,5 +165,13 @@ private static string FindRepositoryRoot() return current?.FullName ?? throw new InvalidOperationException("Unable to locate the repository root."); } + private static string? GetProjectPropertyValue(XDocument document, string propertyName) => + document + .Root? + .Elements("PropertyGroup") + .Elements(propertyName) + .Select(node => node.Value.Trim()) + .FirstOrDefault(value => !string.IsNullOrWhiteSpace(value)); + private static string NormalizePath(string path) => path.Replace('\\', '/'); }