logo SERENITY
Game Systems Foundation
Search Results for

    Show / Hide Table of Contents

    Class WaveCreatorTests

    EditMode tests for WaveCreator. Every test targets fixture paths under a private temp folder — the real project's own Wave/Stage/Character assets, if any, are never touched — and every test passes an explicit DuplicateIdSearchFolder/ CharacterPrefabSearchFolder pinned to Serenity.Wave.Tests.Editor.Builder.WaveCreatorTests.TempFolder so every project-wide scan is hermetic by construction.

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

    Constructors

    WaveCreatorTests()

    Declaration
    public WaveCreatorTests()

    Methods

    Create_ChangedWaveIdNotMatchingAnyExistingAssetInFolder_CreatesANewAssetInsteadOfEditing()

    Declaration
    public void Create_ChangedWaveIdNotMatchingAnyExistingAssetInFolder_CreatesANewAssetInsteadOfEditing()

    Create_ExistingAssetFileRemovedBeforeSecondRun_RollsBackTheFullFieldSet()

    Declaration
    public void Create_ExistingAssetFileRemovedBeforeSecondRun_RollsBackTheFullFieldSet()

    Create_ExistingSetReorderedAndExtendedFailsAtItsOwnVerify_RestoresOriginalOrderAndRollsBackTheNewWave()

    CRITICAL coverage for WaveSetSnapshot.RestoreOnto, previously unreachable from this suite. The first run creates a two-wave set [wave_a, wave_b]. The second run mutates the EXISTING set through ApplyWaveSetFields — reordering to [wave_b, wave_a] AND adding a brand-new third wave (wave_c) — then the set's own VerifyAssetWasWrittenToDisk fails (its file was deleted directly off disk, the same "existing asset, file removed" technique as the wave-config rollback test above — a pure C# throw, no Debug.LogError, so no LogAssert is needed here either).

    This also exercises the Serenity.Global.Infrastructure.Editor.Validation.References.SerenitySafeDeleteScope suppression the type doc on WaveCreator.Create calls out: at the moment rollback deletes the freshly-created wave_c asset, the Wave Set object still holds a LIVE (dirty, not-yet-reverted) reference to it in memory — ApplyWaveSetFields wrote that reference before the verify-and-throw step, and WaveSetSnapshot.RestoreOnto only runs afterward, in RollBack. Without suppression, SerenityAssetReferenceFinder.FindReferencers would find the Wave Set as a referencer of wave_c and intercept the delete. The assertion that wave_c's file is actually gone from disk is the proof the suppression did its job.

    Declaration
    public void Create_ExistingSetReorderedAndExtendedFailsAtItsOwnVerify_RestoresOriginalOrderAndRollsBackTheNewWave()

    Create_ExistingWaveSetLosesAWave_WarnsUnlinkButLeavesTheFileOnDisk()

    Declaration
    public void Create_ExistingWaveSetLosesAWave_WarnsUnlinkButLeavesTheFileOnDisk()

    Create_OrderIsInputOrderNotWaveIndexOrder()

    Declaration
    public void Create_OrderIsInputOrderNotWaveIndexOrder()

    Create_RegisterAsAddressablesFalse_LeavesAddressablesUntouched()

    Declaration
    public void Create_RegisterAsAddressablesFalse_LeavesAddressablesUntouched()

    Create_RegisterAsAddressablesTrue_TagsBothWaveConfigsAndWaveSetWithModuleWave()

    Declaration
    public void Create_RegisterAsAddressablesTrue_TagsBothWaveConfigsAndWaveSetWithModuleWave()

    Create_ReorderingAnExistingSet_PersistsTheNewOrder()

    Declaration
    public void Create_ReorderingAnExistingSet_PersistsTheNewOrder()

    Create_ToConfig_TotalActorsEqualsEntryCountNotTheActorSum()

    Declaration
    public void Create_ToConfig_TotalActorsEqualsEntryCountNotTheActorSum()

    Create_UpdatingExistingAssets_PreservesTheOriginalGuids()

    Declaration
    public void Create_UpdatingExistingAssets_PreservesTheOriginalGuids()

    Create_ValidInput_AssignsANonEmptyGuidToEachAsset()

    Declaration
    public void Create_ValidInput_AssignsANonEmptyGuidToEachAsset()

    Create_ValidInput_CreatesWaveConfigsAndOrderedWaveSet()

    Declaration
    public void Create_ValidInput_CreatesWaveConfigsAndOrderedWaveSet()

    Create_ValidInput_SetsNeedsCompositionRootWiringTrue()

    Declaration
    public void Create_ValidInput_SetsNeedsCompositionRootWiringTrue()

    Preview_ExistingAssets_ReportsNotNewWithTheirRealPaths()

    Declaration
    public void Preview_ExistingAssets_ReportsNotNewWithTheirRealPaths()

    Preview_MultiCountEntry_ReportsEntryCountDifferentFromActorSum()

    Declaration
    public void Preview_MultiCountEntry_ReportsEntryCountDifferentFromActorSum()

    Preview_NeverMutatesTheProject()

    Declaration
    public void Preview_NeverMutatesTheProject()

    SetUp()

    Declaration
    public void SetUp()

    TearDown()

    Declaration
    public void TearDown()

    Validate_ActorMatchingAKnownCharacterPrefab_DoesNotWarnAboutIt()

    Declaration
    public void Validate_ActorMatchingAKnownCharacterPrefab_DoesNotWarnAboutIt()

    Validate_ActorNotAKnownCharacterPrefab_WarnsWithoutBlocking()

    Declaration
    public void Validate_ActorNotAKnownCharacterPrefab_WarnsWithoutBlocking()

    Validate_CaseVariantWaveIdInSameFolder_IsRejectedBecauseAssetFileNamesCollide()

    Serenity Ids are case-sensitive, but a wave's Id also becomes its asset FILE NAME (NamingSanitizer.FileNameSafe), and file names are NOT case-sensitive on Windows/macOS. So 'wave_orange' and 'Wave_Orange' would collide on disk — one asset 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_CaseVariantWaveIdInSameFolder_IsRejectedBecauseAssetFileNamesCollide()

    Validate_DuplicateWaveConfigIdElsewhereDifferingOnlyByCase_StillWarns()

    A case-variant Id in ANOTHER folder is not the file-name-collision defect Validate_CaseVariantWaveIdInSameFolder_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 'wave_orange' and 'Wave_Orange' resolve as two distinct, unambiguous waves. It is still worth a WARNING (never an error) because it is very likely a typo — see Serenity.Global.Infrastructure.Editor.SerenityAssetIdRules.WarnAboutCaseVariantElsewhere``1(Serenity.Global.Infrastructure.Editor.SerenityAssetIdLookup.IdMatches{``0},System.String,System.String,Serenity.Global.Infrastructure.Editor.SerenityCreationValidationResult).

    Declaration
    public void Validate_DuplicateWaveConfigIdElsewhereDifferingOnlyByCase_StillWarns()

    Validate_DuplicateWaveConfigIdElsewhere_WarnsWithoutBlocking()

    Declaration
    public void Validate_DuplicateWaveConfigIdElsewhere_WarnsWithoutBlocking()

    Validate_DuplicateWaveIdWithinBatch_ReturnsError()

    Declaration
    public void Validate_DuplicateWaveIdWithinBatch_ReturnsError()

    Validate_DuplicateWaveIndexAcrossWaves_WarnsWithoutBlocking()

    Declaration
    public void Validate_DuplicateWaveIndexAcrossWaves_WarnsWithoutBlocking()

    Validate_DuplicateWaveSetIdElsewhere_WarnsWithoutBlocking()

    Declaration
    public void Validate_DuplicateWaveSetIdElsewhere_WarnsWithoutBlocking()

    Validate_EmptyWaveId_ReturnsError()

    Declaration
    public void Validate_EmptyWaveId_ReturnsError()

    Validate_EmptyWaveSetId_ReturnsError()

    Declaration
    public void Validate_EmptyWaveSetId_ReturnsError()

    Validate_EntryCountZero_WarnsWithoutBlocking()

    Deviation from a literal "count = 0 error" reading: Serenity.Wave.Domain.Entities.SpawnEntry is a bare abstract class with no validating constructor — nothing in the domain throws on Count < 1, unlike CharacterConfig's real MaxHealth < 1 throw. Per the project's own established convention (a Unity [Min] inspector hint the domain never enforces is a warning, not a blocking error — see CharacterConfigCreatorTests), this is a warning.

    Declaration
    public void Validate_EntryCountZero_WarnsWithoutBlocking()

    Validate_InvalidStageFolderPath_ReturnsError()

    Declaration
    public void Validate_InvalidStageFolderPath_ReturnsError()

    Validate_NegativeSpawnDelayAndCadence_WarnEachWithoutBlocking()

    Declaration
    public void Validate_NegativeSpawnDelayAndCadence_WarnEachWithoutBlocking()

    Validate_NegativeWaveIndex_ReturnsError()

    Declaration
    public void Validate_NegativeWaveIndex_ReturnsError()

    Validate_NoActorAssigned_WarnsMirroringTheDrawerText()

    Declaration
    public void Validate_NoActorAssigned_WarnsMirroringTheDrawerText()

    Validate_NullInput_ReturnsMissingInputError()

    Declaration
    public void Validate_NullInput_ReturnsMissingInputError()

    Validate_ResolvableSpawnPointId_NoErrorAndNoWarningForIt()

    Declaration
    public void Validate_ResolvableSpawnPointId_NoErrorAndNoWarningForIt()

    Validate_SameWaveConfigIdInItsOwnFolder_IsExcludedFromTheDuplicateWarning()

    Declaration
    public void Validate_SameWaveConfigIdInItsOwnFolder_IsExcludedFromTheDuplicateWarning()

    Validate_SameWaveSetIdInItsOwnFolder_IsExcludedFromTheDuplicateWarning()

    Declaration
    public void Validate_SameWaveSetIdInItsOwnFolder_IsExcludedFromTheDuplicateWarning()

    Validate_StageFolderDoesNotExistYet_WarnsDegradedWithoutBlocking()

    Declaration
    public void Validate_StageFolderDoesNotExistYet_WarnsDegradedWithoutBlocking()

    Validate_StageFolderExistsWithNoPrefab_WarnsDegradedWithoutBlocking()

    Declaration
    public void Validate_StageFolderExistsWithNoPrefab_WarnsDegradedWithoutBlocking()

    Validate_StagePrefabHasNoSpawnPointComponents_WarnsWithTheNoComponentsMessage()

    Distinguishes the two situations ScanStagePrefab(string) collapses into the same null/empty result: zero SpawnPoint components at all.

    Declaration
    public void Validate_StagePrefabHasNoSpawnPointComponents_WarnsWithTheNoComponentsMessage()

    Validate_StagePrefabHasSpawnPointsWithBlankIds_WarnsWithTheBlankIdsMessage()

    The other half of the same distinction: one or more SpawnPoint components exist, but every one carries a blank id — ScanStagePrefab filters blank ids out before returning, so this must not be reported as "no SpawnPoint components".

    Declaration
    public void Validate_StagePrefabHasSpawnPointsWithBlankIds_WarnsWithTheBlankIdsMessage()

    Validate_UnresolvableSpawnPointIdWithARealPrefab_ReturnsError()

    Declaration
    public void Validate_UnresolvableSpawnPointIdWithARealPrefab_ReturnsError()

    Validate_WaveIndexNotMatchingPlayOrderPosition_WarnsWithoutBlocking()

    Declaration
    public void Validate_WaveIndexNotMatchingPlayOrderPosition_WarnsWithoutBlocking()

    Validate_ZeroWaves_WarnsWithoutBlocking()

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