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.
Inherited Members
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()