using NUnit.Framework; using ProjectM.Client; using UnityEngine; namespace ProjectM.Tests { /// /// Pure-logic tests for the client settings model (no ECS world): JSON round-trip via JsonUtility, /// defensive clamping of hand-edited/corrupt values, and the GameVolume bus statics. Engine APIs /// (Screen/QualitySettings) resolve in EditMode, so Defaults()/Clamped() are exercisable here. /// public class GameSettingsTests { static GameSettings Sample() => new GameSettings { Version = GameSettings.CurrentVersion, ResWidth = 2560, ResHeight = 1440, RefreshHz = 144, FullScreenMode = (int)FullScreenMode.ExclusiveFullScreen, QualityLevel = 0, VSync = 2, TargetFps = 120, Master = 0.8f, Music = 0.5f, Sfx = 0.3f, }; [Test] public void Json_RoundTrip_PreservesAllFields() { var src = Sample(); var json = JsonUtility.ToJson(src); var dst = JsonUtility.FromJson(json); Assert.AreEqual(src.Version, dst.Version); Assert.AreEqual(src.ResWidth, dst.ResWidth); Assert.AreEqual(src.ResHeight, dst.ResHeight); Assert.AreEqual(src.RefreshHz, dst.RefreshHz); Assert.AreEqual(src.FullScreenMode, dst.FullScreenMode); Assert.AreEqual(src.QualityLevel, dst.QualityLevel); Assert.AreEqual(src.VSync, dst.VSync); Assert.AreEqual(src.TargetFps, dst.TargetFps); Assert.AreEqual(src.Master, dst.Master, 1e-5f); Assert.AreEqual(src.Music, dst.Music, 1e-5f); Assert.AreEqual(src.Sfx, dst.Sfx, 1e-5f); } [Test] public void Clamped_BoundsOutOfRangeValues() { var bad = new GameSettings { ResWidth = 99999, ResHeight = -5, RefreshHz = -10, FullScreenMode = 99, QualityLevel = 9999, VSync = 7, TargetFps = 5, Master = 2f, Music = -1f, Sfx = 3f, }; var c = bad.Clamped(); Assert.LessOrEqual(c.ResWidth, 7680); Assert.GreaterOrEqual(c.ResHeight, 480); Assert.GreaterOrEqual(c.RefreshHz, 0); Assert.That(c.FullScreenMode, Is.InRange(0, 3)); Assert.That(c.VSync, Is.InRange(0, 2)); Assert.AreEqual(1f, c.Master, 1e-5f); // 2f -> 1 Assert.AreEqual(0f, c.Music, 1e-5f); // -1 -> 0 Assert.AreEqual(1f, c.Sfx, 1e-5f); // 3f -> 1 Assert.That(c.QualityLevel, Is.GreaterThanOrEqualTo(0)); // clamped to a valid level index } [Test] public void Clamped_NonPositiveTargetFps_BecomesUncapped() { Assert.AreEqual(-1, new GameSettings { TargetFps = 0 }.Clamped().TargetFps); Assert.AreEqual(-1, new GameSettings { TargetFps = -50 }.Clamped().TargetFps); Assert.AreEqual(120, new GameSettings { TargetFps = 120, Master = 1f }.Clamped().TargetFps); } [Test] public void Defaults_AreValidAndFullVolume() { var d = GameSettings.Defaults(); Assert.AreEqual(GameSettings.CurrentVersion, d.Version); Assert.Greater(d.ResWidth, 0); Assert.Greater(d.ResHeight, 0); Assert.AreEqual(1f, d.Master, 1e-5f); Assert.AreEqual(1f, d.Music, 1e-5f); Assert.AreEqual(1f, d.Sfx, 1e-5f); // Defaults survive a clamp unchanged (they are in-range by construction). var c = d.Clamped(); Assert.AreEqual(d.Master, c.Master, 1e-5f); Assert.AreEqual(d.VSync, c.VSync); } [Test] public void GameVolume_BusesAreSettable_DefaultFull() { float prevMusic = GameVolume.Music, prevSfx = GameVolume.Sfx; try { GameVolume.Music = 0.25f; GameVolume.Sfx = 0.6f; Assert.AreEqual(0.25f, GameVolume.Music, 1e-5f); Assert.AreEqual(0.6f, GameVolume.Sfx, 1e-5f); } finally { GameVolume.Music = prevMusic; GameVolume.Sfx = prevSfx; } } } }