logo SERENITY
Game Systems Foundation
Search Results for

    Show / Hide Table of Contents

    Class CharacterConfigCreatorTests

    EditMode tests for CharacterConfigCreator. Every test targets fixture asset paths under a private temp folder — the real project's own CharacterConfigSO assets, if any, are never touched — and every test passes an explicit FolderPath so folder-scoped resolution never resolves to (or is made ambiguous by) anything the real project ships. DuplicateIdSearchFolder is pinned to Serenity.Character.Tests.Editor.Builder.CharacterConfigCreatorTests.TempFolder in Serenity.Character.Tests.Editor.Builder.CharacterConfigCreatorTests.BuildInput(System.String,System.String) (mirroring GameModeSettingsCreatorTests' PlayerInputSettingsSearchFolder pinning) so the duplicate-Id-elsewhere scan is hermetic by construction rather than by the real project happening to ship zero CharacterConfigSO assets today.

    Inheritance
    object
    CharacterConfigCreatorTests
    Inherited Members
    object.ToString()
    object.Equals(object)
    object.Equals(object, object)
    object.ReferenceEquals(object, object)
    object.GetHashCode()
    object.GetType()
    object.MemberwiseClone()
    Namespace: Serenity.Character.Tests.Editor.Builder
    Assembly: Serenity.Character.Tests.Editor.dll
    Syntax
    public class CharacterConfigCreatorTests

    Constructors

    CharacterConfigCreatorTests()

    Declaration
    public CharacterConfigCreatorTests()

    Methods

    Create_ChangedIdNotMatchingAnyExistingAssetInFolder_CreatesANewAssetInsteadOfEditing()

    Declaration
    public void Create_ChangedIdNotMatchingAnyExistingAssetInFolder_CreatesANewAssetInsteadOfEditing()

    Create_ExistingAssetFileRemovedBeforeSecondRun_RollsBackTheFullFieldSet()

    Declaration
    public void Create_ExistingAssetFileRemovedBeforeSecondRun_RollsBackTheFullFieldSet()

    Create_ExistingAssetWithSameIdInSameFolder_UpdatesInPlaceInsteadOfDuplicating()

    Declaration
    public void Create_ExistingAssetWithSameIdInSameFolder_UpdatesInPlaceInsteadOfDuplicating()

    Create_MaxHealthExactlyOne_PersistsTheBoundaryValue()

    Declaration
    public void Create_MaxHealthExactlyOne_PersistsTheBoundaryValue()

    Create_MountGameRailAddsFollowerThenALaterStageFails_RollsBackByRemovingTheFollower()

    Declaration
    public void Create_MountGameRailAddsFollowerThenALaterStageFails_RollsBackByRemovingTheFollower()

    Create_MountGameRailTwiceOnSamePrefab_UpdatesTheSameFollowerInsteadOfDuplicating()

    Declaration
    public void Create_MountGameRailTwiceOnSamePrefab_UpdatesTheSameFollowerInsteadOfDuplicating()

    Create_MountGameRailUpdatesExistingFollowerThenALaterStageFails_RollsBackByRestoringItsPriorFields()

    Declaration
    public void Create_MountGameRailUpdatesExistingFollowerThenALaterStageFails_RollsBackByRestoringItsPriorFields()

    Create_MountGameRailWithNoPrefab_FailsAndCreatesNoAsset()

    Declaration
    public void Create_MountGameRailWithNoPrefab_FailsAndCreatesNoAsset()

    Create_MountGameRail_AddsUnityRailFollowerViewWithEveryConfiguredField()

    Declaration
    public void Create_MountGameRail_AddsUnityRailFollowerViewWithEveryConfiguredField()

    Create_MountNone_LeavesThePrefabWithoutAUnityRailFollowerView()

    Declaration
    public void Create_MountNone_LeavesThePrefabWithoutAUnityRailFollowerView()

    Create_MountStageSpawnPoint_LeavesThePrefabWithoutAUnityRailFollowerView()

    Declaration
    public void Create_MountStageSpawnPoint_LeavesThePrefabWithoutAUnityRailFollowerView()

    Create_RegisterAsAddressablesFalse_LeavesAddressablesUntouched()

    Declaration
    public void Create_RegisterAsAddressablesFalse_LeavesAddressablesUntouched()

    Create_RegisterAsAddressablesTrue_TagsTheAssetWithTypeCharacter()

    Declaration
    public void Create_RegisterAsAddressablesTrue_TagsTheAssetWithTypeCharacter()

    Create_StaleFolderCacheOnFreshCreation_RollsBackAndLeavesNothing()

    Mirrors GameCameraSettingsCreatorTests.Create_StaleFolderCacheOnFreshCreation_RollsBackAndLeavesNothing exactly (Character shares its single-asset cardinality — there is no registry/profiles split to justify PrefetchPolicyCreator's separate-branch fresh-folder-chain variant). The stale folder is not "freshly created" by this call: SettingsAssetAuthoring.EnsureProjectFolderExists's own top-level AssetDatabase.IsValidFolder check treats a stale-but-cache-valid folder as already existing and returns without creating anything (documented, shared, and already covered by every sibling creator's own version of this test) — so nothing about the folder itself is asserted; only that the write never landed.

    Declaration
    public void Create_StaleFolderCacheOnFreshCreation_RollsBackAndLeavesNothing()

    Create_UpdatingExistingAsset_PreservesTheOriginalGuid()

    Declaration
    public void Create_UpdatingExistingAsset_PreservesTheOriginalGuid()

    Create_ValidInput_AssignsANonEmptyGuid()

    Declaration
    public void Create_ValidInput_AssignsANonEmptyGuid()

    Create_ValidInput_CreatesAssetWithEveryConfiguredField()

    Declaration
    public void Create_ValidInput_CreatesAssetWithEveryConfiguredField()

    Preview_ExistingAssetWithSameId_ReportsNotNewWithItsRealPath()

    Declaration
    public void Preview_ExistingAssetWithSameId_ReportsNotNewWithItsRealPath()

    Preview_NeverMutatesTheProject()

    Declaration
    public void Preview_NeverMutatesTheProject()

    Preview_NoExistingAsset_ReportsIsNewWithTheWouldBeAssetPath()

    Declaration
    public void Preview_NoExistingAsset_ReportsIsNewWithTheWouldBeAssetPath()

    SetUp()

    Declaration
    public void SetUp()

    TearDown()

    Declaration
    public void TearDown()

    Validate_CaseVariantIdInSameFolder_IsRejectedBecauseAssetFileNamesCollide()

    Serenity Ids are case-sensitive, but an archetype's Id also becomes its asset FILE NAME (NamingSanitizer.FileNameSafe), and file names are NOT case-sensitive on Windows/macOS. So 'char_orange' and 'Char_Orange' would collide on disk — one archetype silently overwriting the other — even though they are different, unrelated Ids at runtime. Validate(Input) must reject this with an error (not merely warn), mirroring PrefetchPolicyCreator's own case-insensitive uniqueness check, and Create(Input) must refuse to run at all.

    Declaration
    public void Validate_CaseVariantIdInSameFolder_IsRejectedBecauseAssetFileNamesCollide()

    Validate_DuplicateIdElsewhereDifferingOnlyByCase_StillWarns()

    A case-variant Id in ANOTHER folder is not the file-name-collision defect Validate_CaseVariantIdInSameFolder_IsRejectedBecauseAssetFileNamesCollide() covers — two different folders can each hold their own same-named file on disk. It is also not a runtime ambiguity — Serenity Ids are case-sensitive, so 'char_case_dup' and 'Char_Case_Dup' resolve as two distinct, unambiguous archetypes. It is still worth a WARNING (never an error) because it is very likely a typo.

    Declaration
    public void Validate_DuplicateIdElsewhereDifferingOnlyByCase_StillWarns()

    Validate_DuplicateIdElsewhereInProject_WarnsWithoutBlocking()

    Declaration
    public void Validate_DuplicateIdElsewhereInProject_WarnsWithoutBlocking()

    Validate_EmptyId_ReturnsError()

    Declaration
    public void Validate_EmptyId_ReturnsError()

    Validate_InvalidFolderPath_ReturnsError()

    Declaration
    public void Validate_InvalidFolderPath_ReturnsError()

    Validate_MaxHealthExactlyOne_IsValidWithNoErrorAndNoWarningForIt()

    Guards the MaxHealth < 1 comparison against an off-by-one regression: exactly 1 is the edge of the only domain throw (CharacterConfig's constructor accepts >= 1) and must be treated as fully valid — no error AND no warning — not just "not rejected".

    Declaration
    public void Validate_MaxHealthExactlyOne_IsValidWithNoErrorAndNoWarningForIt()

    Validate_MaxHealthNegative_ReturnsError()

    Declaration
    public void Validate_MaxHealthNegative_ReturnsError()

    Validate_MaxHealthZero_ReturnsError()

    Declaration
    public void Validate_MaxHealthZero_ReturnsError()

    Validate_MountGameRailWithNoPrefab_ReturnsBlockingError()

    Declaration
    public void Validate_MountGameRailWithNoPrefab_ReturnsBlockingError()

    Validate_NegativeAttributeFields_WarnEachWithoutBlocking()

    Declaration
    public void Validate_NegativeAttributeFields_WarnEachWithoutBlocking()

    Validate_NoPrefabAssigned_WarnsMirroringTheInstallersBootWarning()

    Declaration
    public void Validate_NoPrefabAssigned_WarnsMirroringTheInstallersBootWarning()

    Validate_NullInput_ReturnsMissingInputError()

    Declaration
    public void Validate_NullInput_ReturnsMissingInputError()

    Validate_SameIdInASubfolderOfTheOutputFolder_DoesNotWarnBecauseCreateEditsItInPlace()

    The duplicate-Id-elsewhere pass excludes the asset the creator is about to resolve, and the in-folder pass RECURSES — so a same-Id asset in a SUBFOLDER of the output folder is not a duplicate at all: it is the very asset Create will update in place. Warning about it told the author to pick a distinct Id for an operation that was never going to create anything.

    Declaration
    public void Validate_SameIdInASubfolderOfTheOutputFolder_DoesNotWarnBecauseCreateEditsItInPlace()

    Validate_TwoAssetsSharingAnIdInTheOutputFolder_WarnsAboutTheOneItWillNotResolve()

    Two assets carrying the same Id in ONE folder are the ambiguity this warning exists for — which one a by-Id lookup resolves depends on load order. Create never produces this shape, so the second twin is authored directly.

    Declaration
    public void Validate_TwoAssetsSharingAnIdInTheOutputFolder_WarnsAboutTheOneItWillNotResolve()
    In this article
    © 2026 Serenity. All Rights Reserved