v1.3.0 Restructure Saxonite workspace and upgrade to .NET 10 (#1)

Move Saxonite’s projects into a dedicated `Workspace` folder and align the solution with .NET 10 and the current Common workspace. Update encryption integration, test project structure and coverage, and repository guidance and upgrade notes.

- Relocate application and library projects while retaining Git rename history.
- Split tests into Admin, Online, and Shared projects; add representative behavioral and serialization tests.
- Update Common integration, application version, and repository documentation.

Application version: 1.3.0

Reviewed-on: #1
Co-authored-by: andy <andy@sarand.com>
This commit was merged in pull request #1.
This commit is contained in:
2026-10-16 18:24:16 +01:00
committed by andy
parent 2c3fb146ab
commit 9f22b522df
1996 changed files with 1992 additions and 1179 deletions
@@ -0,0 +1,41 @@
using NUnit.Framework;
using Sarand.Net.Standard.Base.Bus;
using Saxonite.Net.Standard.Base.Bus;
namespace Saxonite.Net.Core.UnitTests.Data.Bus
{
//=======================================================================
[TestFixture]
public class SaxArticle_ContentData_Tester
{
//-------------------------------------------------------------------
[Test]
public void ContentDataRoundTripsBodyAndImageSegments()
{
SaxArticle.ContentData content = new SaxArticle.ContentData();
content.AddSegment().Body.Html = "<p>Fish &amp; chips</p>";
content.AddSegment().Image.ItemImageId = new SysId(123);
SaxArticle.ContentData restored = SaxArticle.ExtractContent(SaxArticle.GetContentData(content));
Assert.That(restored.Segments, Has.Count.EqualTo(2));
Assert.That(restored.Segments[0].Body.Html, Is.EqualTo("<p>Fish &amp; chips</p>"));
Assert.That(SysId.ToLong(restored.Segments[1].Image.ItemImageId), Is.EqualTo(123));
}
//-------------------------------------------------------------------
[Test]
public void ContentDataOmitsInvalidSegments()
{
SaxArticle.ContentData content = new SaxArticle.ContentData();
content.AddSegment();
content.AddSegment().Body.Html = "<p>Valid</p>";
SaxArticle.ContentData restored = SaxArticle.ExtractContent(SaxArticle.GetContentData(content));
Assert.That(restored.Segments, Has.Count.EqualTo(1));
Assert.That(restored.Segments[0].Body.Html, Is.EqualTo("<p>Valid</p>"));
}
}
//=======================================================================
}
@@ -0,0 +1,47 @@
using NUnit.Framework;
using Saxonite.Net.Standard.Base.App;
using Saxonite.Net.Standard.Base.Bus;
namespace Saxonite.Net.Core.UnitTests.Data.Bus
{
//=======================================================================
[TestFixture]
public class SaxContactData_Bus_Tester
{
//-------------------------------------------------------------------
[Test]
public void ContactMethodsCanBeUpdatedRemovedAndCleared()
{
SaxContactData data = new SaxContactData();
Assert.That(data.SetContactMethodValue(Sax.ContactMethod.Email, "first@example.com"), Is.True);
Assert.That(data.SetContactMethodValue(Sax.ContactMethod.Email, "second@example.com"), Is.True);
Assert.That(data.GetContactMethodValue(Sax.ContactMethod.Email), Is.EqualTo("second@example.com"));
Assert.That(data.SetContactMethodValue(Sax.ContactMethod.Unknown, "ignored"), Is.False);
Assert.That(data.SetContactMethodValue(Sax.ContactMethod.PhoneMain, ""), Is.False);
Assert.That(data.ClearContactMethod(Sax.ContactMethod.Email), Is.True);
Assert.That(data.ClearContactMethod(Sax.ContactMethod.Email), Is.False);
data.SetContactMethodValue(Sax.ContactMethod.Website, "https://example.com");
data.SetContactMethodValue(Sax.ContactMethod.PhoneMobile, "+1 555 0100");
data.ClearContactMethods();
Assert.That(data.Methods, Is.Empty);
}
//-------------------------------------------------------------------
[Test]
public void ContactDataRoundTripsXmlValues()
{
SaxContactData data = new SaxContactData();
data.SetContactMethodValue(Sax.ContactMethod.Email, "person+tag@example.com & team");
data.SetContactMethodValue(Sax.ContactMethod.PhoneMain, "+1 555 0100");
SaxContactData restored = new SaxContactData(data.GetContactData());
Assert.That(restored.GetContactMethodValue(Sax.ContactMethod.Email), Is.EqualTo("person+tag@example.com & team"));
Assert.That(restored.GetContactMethodValue(Sax.ContactMethod.PhoneMain), Is.EqualTo("+1 555 0100"));
Assert.That(restored.Methods, Has.Count.EqualTo(2));
}
}
//=======================================================================
}
@@ -0,0 +1,47 @@
using NUnit.Framework;
using Saxonite.Net.Standard.Base.App;
using Saxonite.Net.Standard.Base.Bus;
using System;
namespace Saxonite.Net.Core.UnitTests.Data.Bus
{
//=======================================================================
[TestFixture]
public class SaxEligibilityAndEventRules_Tester
{
//-------------------------------------------------------------------
[TestCase(Sax.EligibilityType.Birth, 1)]
[TestCase(Sax.EligibilityType.Naturalised, 1)]
[TestCase(Sax.EligibilityType.Parent, 2)]
[TestCase(Sax.EligibilityType.Grandparent, 4)]
[TestCase(Sax.EligibilityType.Passport, 9)]
[TestCase(Sax.EligibilityType.Visa, 9)]
[TestCase(Sax.EligibilityType.Unknown, 9)]
public void EligibilityTypeHasExpectedInstanceLimit(Sax.EligibilityType type, int expected)
{
Assert.That(SaxUserEligibility.GetMaxInstances(type), Is.EqualTo(expected));
}
//-------------------------------------------------------------------
[TestCase(Sax.EligibilityType.Birth, false)]
[TestCase(Sax.EligibilityType.Parent, false)]
[TestCase(Sax.EligibilityType.Passport, true)]
[TestCase(Sax.EligibilityType.Visa, true)]
[TestCase(Sax.EligibilityType.Unknown, false)]
public void ApplicablePeriodIsLimitedToPassportAndVisa(Sax.EligibilityType type, bool expected)
{
Assert.That(SaxUserEligibility.AllowsApplicablePeriod(type), Is.EqualTo(expected));
}
//-------------------------------------------------------------------
[TestCase(null, false)]
[TestCase("2026-10-16T00:00:00", false)]
[TestCase("2026-10-16T00:01:00", true)]
[TestCase("2026-10-16T12:30:00", true)]
public void EventTimeRejectsMissingAndExactMidnight(DateTime? eventAt, bool expected)
{
Assert.That(SaxOrganisationEvent.HasValidEventTime(eventAt), Is.EqualTo(expected));
}
}
//=======================================================================
}
@@ -0,0 +1,23 @@
using NUnit.Framework;
using Saxonite.Net.Standard.Base.App;
using Saxonite.Net.Standard.Base.Bus;
namespace Saxonite.Net.Core.UnitTests.Data.Bus
{
//=======================================================================
[TestFixture]
public class SaxOrganisation_Bus_Tester
{
//-------------------------------------------------------------------
[TestCase(Sax.OrganisationCategory.Club, true)]
[TestCase(Sax.OrganisationCategory.Association, true)]
[TestCase(Sax.OrganisationCategory.SportDepartment, true)]
[TestCase(Sax.OrganisationCategory.Other, false)]
[TestCase(Sax.OrganisationCategory.Unknown, false)]
public void IsSportMandatory_ReflectsOrganisationCategory(Sax.OrganisationCategory category, bool expected)
{
Assert.That(SaxOrganisation.IsSportMandatory(category), Is.EqualTo(expected));
}
}
//=======================================================================
}
@@ -0,0 +1,36 @@
using NUnit.Framework;
using Saxonite.Net.Standard.Base.App;
using Saxonite.Net.Standard.Base.Bus;
using System.Collections.Generic;
namespace Saxonite.Net.Core.UnitTests.Data.Bus
{
//=======================================================================
[TestFixture]
public class SaxRegion_Bus_Tester
{
//-------------------------------------------------------------------
[TestCase(Sax.RegionType.World, Sax.RegionType.Galaxy, true)]
[TestCase(Sax.RegionType.Continent, Sax.RegionType.World, true)]
[TestCase(Sax.RegionType.Country, Sax.RegionType.SubContinent, true)]
[TestCase(Sax.RegionType.Province, Sax.RegionType.Nation, true)]
[TestCase(Sax.RegionType.Province, Sax.RegionType.State, false)]
[TestCase(Sax.RegionType.Unknown, Sax.RegionType.World, false)]
public void IsValidParentRegionType_ReflectsRegionHierarchy(Sax.RegionType regionType, Sax.RegionType parentType, bool expected)
{
Assert.That(SaxRegion.IsValidParentRegionType(regionType, parentType), Is.EqualTo(expected));
}
//-------------------------------------------------------------------
[Test]
public void GetValidParentRegionTypes_ReturnsAnIndependentList()
{
List<Sax.RegionType> parentTypes = SaxRegion.GetValidParentRegionTypes(Sax.RegionType.Country);
parentTypes.Clear();
Assert.That(SaxRegion.GetValidParentRegionTypes(Sax.RegionType.Country),
Is.EquivalentTo(new[] { Sax.RegionType.Continent, Sax.RegionType.SubContinent }));
}
}
//=======================================================================
}
@@ -0,0 +1,21 @@
using NUnit.Framework;
using Saxonite.Net.Standard.Base.Bus;
namespace Saxonite.Net.Core.UnitTests.Data.Bus
{
//=======================================================================
[TestFixture]
public class SaxUserAccount_DisplayName_Tester
{
//-------------------------------------------------------------------
[TestCase("Dr", "Ada", "Lovelace", "Dr Ada Lovelace")]
[TestCase(null, "Ada", "Lovelace", "Ada Lovelace")]
[TestCase("Dr", null, "Lovelace", "Dr Lovelace")]
[TestCase(null, null, null, "")]
public void DisplayNameJoinsPresentNameParts(string title, string firstName, string lastName, string expected)
{
Assert.That(SaxUserAccount.GetDisplayName(title, firstName, lastName), Is.EqualTo(expected));
}
}
//=======================================================================
}