using System; using System.Collections; using System.Collections.Generic; using NUnit.Framework; using UnityEngine; using UnityEngine.TestTools; namespace NEG.Utils.Achievments.Tests { using AchievmentTypes; using static Internal.Extensions; public class ConfigTests { public const string AchievmentsLabel = "TestAchievments"; public const string AchievmentIdToggle = "TOGGLE"; public const string AchievmentIdInt = "INT"; public const string AchievmentIdFloat = "FLOAT"; public const string AchievmentIdInvalid = "huptyrz"; public const int RandomProgress = 15; public const int ProgressChangeDelta = 15; public const int CompletedProgress = 100; public const int OvershootProgress = 150; #region Id And Types [Test] public void AchivmentInvalidId() { AchievmentManager manager = AchievmentManager.Builder.FromLabeledConfig(AchievmentsLabel).Build(); TestInvalidId(AchievmentIdInvalid, (id) => manager.GetAchievmentForId(id), "Get"); } [Test] public void AchivmentInvalidType() { AchievmentManager manager = AchievmentManager.Builder.FromLabeledConfig(AchievmentsLabel).Build(); manager.TestInvalidType(AchievmentIdToggle, "Toggle"); manager.TestInvalidType(AchievmentIdInt, "Int"); manager.TestInvalidType(AchievmentIdFloat, "Float"); } [Test] public void AchivmentCorrectIdAndType() { AchievmentManager manager = AchievmentManager.Builder.FromLabeledConfig(AchievmentsLabel).Build(); manager.TestValidIdAndType(AchievmentIdToggle, "Toggle"); manager.TestValidIdAndType(AchievmentIdInt, "Int"); manager.TestValidIdAndType(AchievmentIdFloat, "Float"); } #endregion #region Toggle [Test] public void AchivmentToggleSet() { var callbackTester = new TestCallbackRereiver(); AchievmentManager manager = AchievmentManager.Builder.FromLabeledConfig(AchievmentsLabel) .WithCallbackReciever(callbackTester) .Build(); manager.SetToggleAchivment(AchievmentIdToggle); callbackTester.TestCompleted(AchievmentIdToggle); callbackTester.Reset(); manager.SetToggleAchivment(AchievmentIdToggle); callbackTester.TestNoChanges(); } #endregion #region Int [Test] public void AchivmentIntSetLess() { var callbackTester = new TestCallbackRereiver(); AchievmentManager manager = AchievmentManager.Builder.FromLabeledConfig(AchievmentsLabel) .WithCallbackReciever(callbackTester) .Build(); //Set progress to some value progress manager.SetIntProgress(AchievmentIdInt, RandomProgress); var data = callbackTester.GetChanged(); Assert.AreEqual(RandomProgress, data.CurrentProgress); Assert.IsFalse(data.IsCompleted); callbackTester.Reset(); } [Test] public void AchivmentIntSetEqual() { var callbackTester = new TestCallbackRereiver(); AchievmentManager manager = AchievmentManager.Builder.FromLabeledConfig(AchievmentsLabel) .WithCallbackReciever(callbackTester) .Build(); //Set progress to some value equal to required value manager.SetIntProgress(AchievmentIdInt, CompletedProgress); var data = callbackTester.GetChanged(); Assert.AreEqual(CompletedProgress, data.CurrentProgress); callbackTester.TestCompleted(AchievmentIdInt); callbackTester.Reset(); //Do that again, this time nothing sould change manager.SetIntProgress(AchievmentIdInt, CompletedProgress); callbackTester.TestNoChanges(); callbackTester.Reset(); } [Test] public void AchivmentIntSetGreater() { var callbackTester = new TestCallbackRereiver(); AchievmentManager manager = AchievmentManager.Builder.FromLabeledConfig(AchievmentsLabel) .WithCallbackReciever(callbackTester) .Build(); //Set progress to some value greater than required manager.SetIntProgress(AchievmentIdInt, OvershootProgress); var data = callbackTester.GetChanged(); //Testing against completed progress, should be clamped down Assert.AreEqual(CompletedProgress, data.CurrentProgress); callbackTester.TestCompleted(AchievmentIdInt); callbackTester.Reset(); //Do that again, this time nothing sould change manager.SetIntProgress(AchievmentIdInt, OvershootProgress); callbackTester.TestNoChanges(); callbackTester.Reset(); } [Test] public void AchivmentIntChangeCompletion() { var callbackTester = new TestCallbackRereiver(); AchievmentManager manager = AchievmentManager.Builder.FromLabeledConfig(AchievmentsLabel) .WithCallbackReciever(callbackTester) .Build(); //Add progresss one interval below completion for (int i = 0; i < CompletedProgress / ProgressChangeDelta; i++) { manager.ChangeIntProgress(AchievmentIdInt, ProgressChangeDelta); callbackTester.TestNotCompleted(); var changed = callbackTester.GetChanged(); Assert.AreEqual((i + 1) * ProgressChangeDelta, changed.CurrentProgress); callbackTester.Reset(); } //Add progress one more time, should now be completed manager.ChangeIntProgress(AchievmentIdInt, ProgressChangeDelta); var changed1 = callbackTester.GetChanged(); Assert.AreEqual(CompletedProgress, changed1.CurrentProgress); callbackTester.TestCompleted(AchievmentIdInt); callbackTester.Reset(); //Do that again, this time nothing should change manager.ChangeIntProgress(AchievmentIdInt, ProgressChangeDelta); callbackTester.TestNoChanges(); callbackTester.Reset(); //Do that again, but down this time also nothing should change manager.ChangeIntProgress(AchievmentIdInt, -ProgressChangeDelta); callbackTester.TestNoChanges(); callbackTester.Reset(); } #endregion #region Float [Test] public void AchivmentFloatSetLess() { var callbackTester = new TestCallbackRereiver(); AchievmentManager manager = AchievmentManager.Builder.FromLabeledConfig(AchievmentsLabel) .WithCallbackReciever(callbackTester) .Build(); //Set progress to some value progress manager.SetFloatProgress(AchievmentIdFloat, RandomProgress); var data = callbackTester.GetChanged(); Assert.AreEqual((float)RandomProgress, data.CurrentProgress); Assert.IsFalse(data.IsCompleted); callbackTester.Reset(); } [Test] public void AchivmentFloatSetEqual() { var callbackTester = new TestCallbackRereiver(); AchievmentManager manager = AchievmentManager.Builder.FromLabeledConfig(AchievmentsLabel) .WithCallbackReciever(callbackTester) .Build(); //Set progress to some value equal to required value manager.SetFloatProgress(AchievmentIdFloat, CompletedProgress); var data = callbackTester.GetChanged(); Assert.AreEqual((float)CompletedProgress, data.CurrentProgress); callbackTester.TestCompleted(AchievmentIdFloat); callbackTester.Reset(); //Do that again, this time nothing sould change manager.SetFloatProgress(AchievmentIdFloat, CompletedProgress); callbackTester.TestNoChanges(); callbackTester.Reset(); } [Test] public void AchivmentFloatSetGreater() { var callbackTester = new TestCallbackRereiver(); AchievmentManager manager = AchievmentManager.Builder.FromLabeledConfig(AchievmentsLabel) .WithCallbackReciever(callbackTester) .Build(); //Set progress to some value greater than required manager.SetFloatProgress(AchievmentIdFloat, OvershootProgress); var data = callbackTester.GetChanged(); //Testing against completed progress, should be clamped down Assert.AreEqual((float)CompletedProgress, data.CurrentProgress); callbackTester.TestCompleted(AchievmentIdFloat); callbackTester.Reset(); //Do that again, this time nothing sould change manager.SetFloatProgress(AchievmentIdFloat, OvershootProgress); callbackTester.TestNoChanges(); callbackTester.Reset(); } [Test] public void AchivmentFloatChangeCompletion() { var callbackTester = new TestCallbackRereiver(); AchievmentManager manager = AchievmentManager.Builder.FromLabeledConfig(AchievmentsLabel) .WithCallbackReciever(callbackTester) .Build(); //Add progresss one interval below completion for (int i = 0; i < CompletedProgress / ProgressChangeDelta; i++) { manager.ChangeFloatProgress(AchievmentIdFloat, ProgressChangeDelta); callbackTester.TestNotCompleted(); var changed = callbackTester.GetChanged(); Assert.AreEqual((i + 1) * ProgressChangeDelta, changed.CurrentProgress, 0.0f); callbackTester.Reset(); } //Add progress one more time, should now be completed manager.ChangeFloatProgress(AchievmentIdFloat, ProgressChangeDelta); var changed1 = callbackTester.GetChanged(); Assert.AreEqual((float)CompletedProgress, changed1.CurrentProgress); callbackTester.TestCompleted(AchievmentIdFloat); callbackTester.Reset(); //Do that again, this time nothing should change manager.ChangeFloatProgress(AchievmentIdFloat, ProgressChangeDelta); callbackTester.TestNoChanges(); callbackTester.Reset(); //Do that again, but down this time also nothing should change manager.ChangeFloatProgress(AchievmentIdFloat, -ProgressChangeDelta); callbackTester.TestNoChanges(); callbackTester.Reset(); } #endregion private class TestCallbackRereiver : IAchievmentCallbackReciever { public AchievmentData LastDataUpdated { get; private set; } = null; public Type LastTypeSet { get; private set; } = null; public string LastIdSet { get; private set; } = null; public void Reset() { LastDataUpdated = null; LastTypeSet = null; LastIdSet = null; } public T GetChanged() where T : AchievmentData { Assert.IsInstanceOf(typeof(T), LastDataUpdated); return (T)LastDataUpdated; } public void TestNoChanges() { Assert.IsNull(LastDataUpdated); Assert.IsNull(LastTypeSet); Assert.IsNull(LastIdSet); } public void TestNotCompleted() { //No need to also check LastTypeSet, they are both set or bot null Assert.IsNull(LastIdSet); } public void TestCompleted(string id) { Assert.AreEqual(typeof(Type), LastTypeSet); Assert.AreEqual(id, LastIdSet); //Shold not be null: if we axpect achievment to be completed it must have also been updated Assert.IsTrue(LastDataUpdated.IsCompleted); } public void AchievmentCompleted(AchievmentData achievment) { LastTypeSet = achievment.GetType(); LastIdSet = achievment.Achievment.Id; } public void AchievmentStateChanged(AchievmentData achievment) { LastDataUpdated = achievment; } } } namespace Internal { public static class Extensions { public static void TestValidIdAndType(this AchievmentManager manager, string id, string testName) where Type : AchievmentData { TestValidIdAndType(id, (id) => manager.GetAchievmentForId(id), testName); } public static void TestValidIdAndType(string id, Action manipulation, string testName) { Assert.DoesNotThrow(() => manipulation(id), $"{testName}: Invalid type or id"); } public static void TestInvalidId(this AchievmentManager manager, string id, string testName) { TestInvalidId(id, (id) => manager.GetAchievmentForId(id), testName); } public static void TestInvalidId(string id, Action manipulation, string testName) { var exception = Assert.Throws(() => manipulation(id), $"Expected to fail with {typeof(AchievmentTypeException)}"); Assert.AreEqual(exception.Id, id, $"{testName}: Achievment id does not match"); } public static void TestInvalidType(this AchievmentManager manager, string id, string testName) where Expected : AchievmentData where Actual : AchievmentData { TestInvalidType(id, (id) => manager.GetAchievmentForId(id), testName); } public static void TestInvalidType(string id, Action manipulation, string testName) where Expected : AchievmentData where Actual : AchievmentData { var exception = Assert.Throws(() => manipulation(id), $"Expected to fail with {typeof(AchievmentTypeException)}"); Assert.AreEqual(id, exception.Id, $"{testName}: Achievment id does not match"); Assert.AreSame(typeof(Expected), exception.Expected, $"{testName}: Target achievment type does not match"); Assert.AreSame(typeof(Actual), exception.Actual, $"{testName}: Actual achievment type does not match"); } } } }