Class GameGraphicsSettingsCreatorTests
EditMode tests for GameGraphicsSettingsCreator. Every test targets fixture assets under a
private temp folder via Input.OutputFolderPath (and, for the settings asset itself, its explicit
path test seam, plus Input.DefinitionSearchFolder for binding-key resolution) — the real
project's own shipped UnityGameGraphicsSettings and Graphics_* definition assets under
Assets/Serenity/Media/GameGraphics/ and Assets/Serenity/Media/GameSettings/ are never
read as a resolution target, so these tests stay hermetic regardless of what the project already ships.
Inherited Members
Namespace: Serenity.GameGraphics.Tests.Editor.Builder
Assembly: Serenity.GameGraphics.Tests.Editor.dll
Syntax
public class GameGraphicsSettingsCreatorTests
Constructors
GameGraphicsSettingsCreatorTests()
Declaration
public GameGraphicsSettingsCreatorTests()
Methods
ApplyInputToDraft_EveryAssetFieldHasALikeNamedInputFieldOrIsExplicitlyExcluded()
Declaration
public void ApplyInputToDraft_EveryAssetFieldHasALikeNamedInputFieldOrIsExplicitlyExcluded()
Create_CreateMissingDefinitionButOneAlreadyExists_DoesNotCreateADuplicate()
Declaration
public void Create_CreateMissingDefinitionButOneAlreadyExists_DoesNotCreateADuplicate()
Create_CreateMissingDefinitionForAllThreeKeys_CreatesLabeledDefinitionsBoundByKey()
Declaration
public void Create_CreateMissingDefinitionForAllThreeKeys_CreatesLabeledDefinitionsBoundByKey()
Create_CreateMissingDefinitionWithOnlyACaseVariantExisting_StillCreatesTheExactCasedOne()
Documents the deliberate ordinal (case-sensitive) match used to resolve a binding key against an
existing definition's Id — see GameGraphicsSettingsCreator's type doc: the runtime's
own Dictionary<string, GameSettingsEntity> lookup is case-sensitive, so a case-variant
existing Id is a genuinely different runtime key, not a duplicate — 'create missing' must still
create the exact-cased definition the settings asset is about to bind to.
Declaration
public void Create_CreateMissingDefinitionWithOnlyACaseVariantExisting_StillCreatesTheExactCasedOne()
Create_DefinitionPersistsButLaterSettingsAssetCreationFails_RollsBackTheAlreadyCreatedDefinitionToo()
Mid-chain rollback within a SINGLE Create() call: the Quality Level definition is created and persisted successfully first (a normal, valid folder), then the LATER settings-asset step fails (its own explicit path points into a stale, cache-valid-but-disk-missing folder — the same established technique as Create_StaleFolderCacheOnFreshCreation_RollsBackAndLeavesNothing(), scoped only to the settings asset's own folder so the earlier definition step is unaffected). The already-persisted definition — and its Addressables entry — must be rolled back too, not just left behind because "it already succeeded".
Declaration
public void Create_DefinitionPersistsButLaterSettingsAssetCreationFails_RollsBackTheAlreadyCreatedDefinitionToo()
Create_ExistingAssetSeededOnEverySerializedField_RestoresThemAll()
Field-by-field regression guard for the generic capture Create(Input)
now rolls back through (transaction.TrackExistingAsset), replacing the hand-rolled
ExistingSettingsSnapshot class this migration deleted. Writes a distinct value into EVERY
serialized field of a real UnityGameGraphicsSettings via reflection — not just the
eight fields Serenity.Global.Infrastructure.Editor.SerenityWizardScratchDraft`1.CopyOnto(`0,`0) happens to write — forces the
update run to fail via the same planted-and-deleted-file technique
Create_SettingsFileRemovedBeforeSecondRun_RollsBackToPreCallValues() uses, and asserts
every field comes back. Proves the capture covers whatever the type declares, not a hand-maintained
field list a future field addition could silently outgrow.
Declaration
public void Create_ExistingAssetSeededOnEverySerializedField_RestoresThemAll()
Create_ExistingSettingsAtSameExplicitPath_UpdatesInPlace()
Declaration
public void Create_ExistingSettingsAtSameExplicitPath_UpdatesInPlace()
Create_FreshSettingsAsset_SerializesEveryFieldWithNonDefaultValues()
Contract test for the ctor-bypass hazard documented on GameGraphicsSettingsCreator.ApplyFields: UnityEngine.ScriptableObject.CreateInstance``1 bypasses UnityGameGraphicsSettings' only constructor entirely, so this run's explicit field assignments are the ONLY thing that gets a value into the serialized asset — this is exactly how the project's own shipped GameGraphicsSettings.asset ended up shipping with four fields silently absent. Every value here deliberately differs from the class's own C# field initializers (e.g. DefaultIsFullScreen = false, the class default is true) so a field that was silently left at its untouched default — rather than actually being written by this run — would be caught, not accidentally match by coincidence.
Declaration
public void Create_FreshSettingsAsset_SerializesEveryFieldWithNonDefaultValues()
Create_MoveFromPackagePath_MovesTheAssetThenUpdatesItAtTheNewPath()
Declaration
public void Create_MoveFromPackagePath_MovesTheAssetThenUpdatesItAtTheNewPath()
Create_MoveFromPackagePath_RollsTheMoveBackWhenTheRunFails()
Forces a failure AFTER the move already committed to disk — the same stale-folder-cache trick Create_StaleFolderCacheOnFreshCreation_RollsBackAndLeavesNothing() uses, here applied to the Quality Level definition's "create missing" step, which Create(Input) runs AFTER the move. The move must be inverted along with everything else this run rolled back.
Declaration
public void Create_MoveFromPackagePath_RollsTheMoveBackWhenTheRunFails()
Create_MoveFromPackagePath_WhenIdDiffersFromFileName_MovesToTheOriginalFileName()
Regression coverage for the real trap in SerenityPackageContentRelocator.MoveIntoFolder
keeping the SOURCE file name unconditionally: the shipped fixture's Id ("some-other-id") and its
file name ("OriginalFileName") are deliberately different here, and Serenity.GameGraphics.Tests.Editor.Builder.GameGraphicsSettingsCreatorTests.BuildInput(System.String)'s own
Id ("totally-unrelated-input-id") differs from both — proving neither string drives the destination
path, only the fixture's own original file name does, exactly as
Serenity.Global.Infrastructure.Editor.SerenityWizardTargetAsset.PlannedTargetPath(System.String,System.String) now also plans it for the window.
Declaration
public void Create_MoveFromPackagePath_WhenIdDiffersFromFileName_MovesToTheOriginalFileName()
Create_RegisterAsAddressablesFalse_LeavesAddressablesUntouched()
Declaration
public void Create_RegisterAsAddressablesFalse_LeavesAddressablesUntouched()
Create_RegisterAsAddressablesTrue_LabelsSettingsAssetForModuleGameGraphics()
Declaration
public void Create_RegisterAsAddressablesTrue_LabelsSettingsAssetForModuleGameGraphics()
Create_SettingsFileRemovedBeforeSecondRun_RollsBackToPreCallValues()
Exercises the resolve-or-edit rollback path: the settings asset is mutated in memory first (via the update path), then its pre-persist disk check fails (its asset file was removed from disk after the first Create() call). ALL EIGHT fields GameGraphicsSettingsCreator.ApplyFields touches must be restored to their pre-call values — not just a couple of them — since a partial restore would silently reintroduce the exact "some fields never got written" defect this wizard exists to prevent (see the verified live GameGraphicsSettings.asset repair this change also made).
Declaration
public void Create_SettingsFileRemovedBeforeSecondRun_RollsBackToPreCallValues()
Create_StaleFolderCacheOnFreshCreation_RollsBackAndLeavesNothing()
The create-path counterpart: a stale, cache-valid-but-disk-missing destination folder makes the very first UnityEditor.AssetDatabase.CreateAsset(UnityEngine.Object,System.String) call fail natively, forcing a rollback of a brand-new run before the settings asset (or either definition) exists. Nothing must be left dangling — no asset, no Addressables entry.
Declaration
public void Create_StaleFolderCacheOnFreshCreation_RollsBackAndLeavesNothing()
Create_UnderAmbiguousMultipleExistingSettings_CreatesANewOneWithoutMutatingEitherExisting()
Declaration
public void Create_UnderAmbiguousMultipleExistingSettings_CreatesANewOneWithoutMutatingEitherExisting()
Create_UpdateRunAgainstAnExistingAsset_DoesNotCreateTheOutputFolder()
Regression test for the stray-folder bug this change fixes: an update-in-place run used to
unconditionally ensure Input.OutputFolderPath even though the resolved existing asset lives
entirely elsewhere (an explicit SettingsAssetPath match), leaving an empty folder behind. The
second run below resolves the SAME existing asset via Serenity.GameGraphics.Tests.Editor.Builder.GameGraphicsSettingsCreatorTests.SettingsPath but names a
different, not-yet-existing Serenity.GameGraphics.Tests.Editor.Builder.GameGraphicsSettingsCreatorTests.ProbeOutputFolder as its OutputFolderPath — exactly
the "editing an asset that lives elsewhere while some unrelated output folder is also configured"
shape the Create Graphics Settings wizard reproduced.
Declaration
public void Create_UpdateRunAgainstAnExistingAsset_DoesNotCreateTheOutputFolder()
Create_ValidInput_CreatesSettingsWithAllFieldsApplied()
Declaration
public void Create_ValidInput_CreatesSettingsWithAllFieldsApplied()
OneTimeTearDown()
Every per-test deletion above goes through the AssetDatabase API, which stays consistent without a manual refresh between tests — flushing to disk once after the whole fixture is enough.
Declaration
public void OneTimeTearDown()
SetUp()
Declaration
public void SetUp()
TearDown()
Declaration
public void TearDown()
Validate_CreateMissingDefinitionButAlreadyExists_WarnsNoOp()
Declaration
public void Validate_CreateMissingDefinitionButAlreadyExists_WarnsNoOp()
Validate_CreateMissingDefinitionWithOnlyACaseVariantExisting_WarnsWithDidYouMean()
Declaration
public void Validate_CreateMissingDefinitionWithOnlyACaseVariantExisting_WarnsWithDidYouMean()
Validate_CreateMissingSelectableDefinitionWithNoOptions_Warns()
Declaration
public void Validate_CreateMissingSelectableDefinitionWithNoOptions_Warns()
Validate_EmptyQualityLevelKey_ReturnsError()
Declaration
public void Validate_EmptyQualityLevelKey_ReturnsError()
Validate_EmptyScreenResolutionKey_WarnsWithoutBlocking()
Declaration
public void Validate_EmptyScreenResolutionKey_WarnsWithoutBlocking()
Validate_KeyDoesNotResolveToExistingDefinition_WarnsWithoutBlocking()
Declaration
public void Validate_KeyDoesNotResolveToExistingDefinition_WarnsWithoutBlocking()
Validate_KeyIsCaseVariantOfExistingDefinition_WarnsWithDidYouMeanAndActualId()
The near-miss safety net over ordinal-only resolution: when the exact key resolves to nothing but a case-variant Id does, the warning must name the actual Id explicitly ("did you mean") rather than the generic "does not match any existing" wording — a user staring at 'graphics_qualitylevel' vs. 'Graphics_QualityLevel' has no way to spot the only difference is case without it being named.
Declaration
public void Validate_KeyIsCaseVariantOfExistingDefinition_WarnsWithDidYouMeanAndActualId()
Validate_KeyResolvesToExistingDefinition_NoWarning()
Declaration
public void Validate_KeyResolvesToExistingDefinition_NoWarning()
Validate_MoveFromPackagePath_NotPackageContent_Errors()
Declaration
public void Validate_MoveFromPackagePath_NotPackageContent_Errors()
Validate_MultipleSettingsAssetsExistInProject_WarnsAboutAmbiguityWithoutBlocking()
Declaration
public void Validate_MultipleSettingsAssetsExistInProject_WarnsAboutAmbiguityWithoutBlocking()
Validate_NullInput_ReturnsMissingInputError()
Declaration
public void Validate_NullInput_ReturnsMissingInputError()
Validate_OutputFolderOutsideAssets_ReturnsError()
Declaration
public void Validate_OutputFolderOutsideAssets_ReturnsError()