From f0a6b70ae3aa7dba39d0f2fbd06996e7042d3727 Mon Sep 17 00:00:00 2001 From: CoderGamester <game.gamester@gmail.com> Date: Thu, 10 Oct 2024 22:25:17 +0100 Subject: [PATCH] Improved the *ObservableResolverList* and *ObservableResolverDictionary* data types to properly resolve lists and dictionaries with different data types from the original collection. Fixed Unit tests for floatPTests that were failing. Added new unit tests for *ObservableResolverList* and *ObservableResolverDictionary* data types --- CHANGELOG.md | 29 +- Runtime/ObservableDictionary.cs | 188 +++++++++++- Runtime/ObservableList.cs | 149 ++++++++-- Tests/Editor/OberservableResolverListTest.cs | 70 +++++ .../OberservableResolverListTest.cs.meta | 11 + Tests/Editor/ObservableDictionaryTest.cs | 275 ++++++++++-------- Tests/Editor/ObservableListTest.cs | 137 +++------ .../ObservableResolverDictionaryTest.cs | 89 ++++++ .../ObservableResolverDictionaryTest.cs.meta | 11 + Tests/Editor/floatPTests.cs | 41 ++- package.json | 4 +- 11 files changed, 742 insertions(+), 262 deletions(-) create mode 100644 Tests/Editor/OberservableResolverListTest.cs create mode 100644 Tests/Editor/OberservableResolverListTest.cs.meta create mode 100644 Tests/Editor/ObservableResolverDictionaryTest.cs create mode 100644 Tests/Editor/ObservableResolverDictionaryTest.cs.meta diff --git a/CHANGELOG.md b/CHANGELOG.md index a93a613..07b5f96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,13 +4,38 @@ All notable changes to this package will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [0.6.0] - 2023-08-05 + +- Improved the *ObservableResolverList* and *ObservableResolverDictionary* data types to properly resolve lists and dictionaries with different data types from the original collection. + +## [0.5.1] - 2023-09-04 + +- Added StructPair data type to support both object and struct type containers, improving memory usage performance. + +**Fix**: +- Fixed the dispose extension methods for GameObject and Object, removing pragma directives and adding null reference check in GetValid method to avoid unwanted exceptions + +## [0.5.0] - 2023-08-05 + +- Added **floatP**, a deterministic floating-point number type, enhancing precision and predictability in mathematical operations. Including arithmetic and comparison operators for floatP to support complex calculations and conversion methods between floatP and float types. + +## [0.4.0] - 2023-07-30 + +- Added utility methods and extensions for Unity's Object and GameObject types, enhancing the codebase's functionality. +- Introduced a SerializableType struct for viewing, modifying, and saving types from the inspector, with serialization support and compatibility with filter attributes. + +## [0.3.0] - 2023-07-28 + +- Added support for observing field updates with previous and current values in the ObservableField class. +- Introduced a UnitySerializedDictionary class that allows serialization of dictionaries in Unity. + ## [0.2.0] - 2020-09-28 -- Removed *ObservableIdList* because it's behaviour was too confusing and the same result can be obtained with *ObservableList* or *ObservableDictionary* - Added new *ObservableResolverList*, *ObservableResolverDictionary* & *ObservableResolverField* to allow to create observable types without referencing the collection directly -- Added Unit tests to all types +- Added Unit tests to all data types in the project **Changed**: +- Removed *ObservableIdList* because it's behaviour was too confusing and the same result can be obtained with *ObservableList* or *ObservableDictionary* - Removed all Pair Data and moved them to new *Pair<Key,Value>* serialized type that can now be serializable on Unity 2020.1 - Moved all Vector2, Vector3 & Vector4 extensions to the ValueData file diff --git a/Runtime/ObservableDictionary.cs b/Runtime/ObservableDictionary.cs index 83e07f8..94ce25b 100644 --- a/Runtime/ObservableDictionary.cs +++ b/Runtime/ObservableDictionary.cs @@ -1,7 +1,9 @@ +using NUnit.Framework; using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; +using UnityEngine.UIElements; // ReSharper disable once CheckNamespace @@ -19,6 +21,9 @@ public interface IObservableDictionary : IEnumerable } /// <inheritdoc cref="IObservableDictionary"/> + /// <remarks> + /// This dictionary only allows to read the elements in it and not to modify it + /// </remarks> public interface IObservableDictionaryReader<TKey, TValue> : IObservableDictionary, IEnumerable<KeyValuePair<TKey, TValue>> { /// <summary> @@ -71,7 +76,7 @@ public interface IObservableDictionaryReader<TKey, TValue> : IObservableDictiona void StopObservingAll(object subscriber = null); } - /// <inheritdoc /> + /// <inheritdoc cref="IObservableDictionary"/> public interface IObservableDictionary<TKey, TValue> : IObservableDictionaryReader<TKey, TValue> { /// <summary> @@ -86,12 +91,77 @@ public interface IObservableDictionary<TKey, TValue> : IObservableDictionaryRead /// <inheritdoc cref="Dictionary{TKey,TValue}.Remove" /> bool Remove(TKey key); + /// <inheritdoc cref="Dictionary{TKey,TValue}.Clear"/> + void Clear(); + /// <remarks> /// It invokes any update method that is observing to the given <paramref name="key"/> on this dictionary /// </remarks> void InvokeUpdate(TKey key); } + /// <inheritdoc /> + /// <remarks> + /// This interface resolves between 2 dictionaries with different types of keys and values + /// </remarks> + public interface IObservableResolverDictionaryReader<TKey, TValue, TKeyOrigin, TValueOrigin> : + IObservableDictionaryReader<TKey, TValue> + { + /// <summary> + /// The Original Dictionary that is being resolved across the entire interface + /// </summary> + ReadOnlyDictionary<TKeyOrigin, TValueOrigin> OriginDictionary { get; } + + /// <summary> + /// Gets the value from the origin dictionary corresponding to the specified key. + /// </summary> + /// <param name="key">The key to locate in the origin dictionary.</param> + /// <returns>The value from the origin dictionary corresponding to the specified key.</returns> + TValueOrigin GetOriginValue(TKey key); + + /// <summary> + /// Attempts to get the value from the origin dictionary corresponding to the specified key. + /// </summary> + /// <param name="key">The key to locate in the origin dictionary.</param> + /// <param name="value">When this method returns, contains the value from the origin dictionary corresponding to the specified key, if the key is found; otherwise, the default value for the type of the value parameter. This parameter is passed uninitialized.</param> + /// <returns>true if the origin dictionary contains an element with the specified key; otherwise, false.</returns> + bool TryGetOriginValue(TKey key, out TValueOrigin value); + } + + /// <inheritdoc cref="IObservableDictionary{TKey,TValue}"/> + /// <remarks> + /// This interface resolves between 2 dictionaries with different types of keys and values + /// </remarks> + public interface IObservableResolverDictionary<TKey, TValue, TKeyOrigin, TValueOrigin> : + IObservableResolverDictionaryReader<TKey, TValue, TKeyOrigin, TValueOrigin>, + IObservableDictionary<TKey, TValue> + { + /// <summary> + /// Updates the value in the origin dictionary corresponding to the specified origin key. + /// </summary> + /// <param name="key">The key of the value to update in the origin dictionary.</param> + /// <param name="value">The new value to set in the origin dictionary.</param> + void UpdateOrigin(TKeyOrigin key, TValueOrigin value); + + /// <inheritdoc cref="Dictionary{TKey,TValue}.Add" /> + /// <remarks> + /// Add's to the origin dictionary + /// </remarks> + void AddOrigin(TKeyOrigin key, TValueOrigin value); + + /// <inheritdoc cref="Dictionary{TKey,TValue}.Remove" /> + /// <remarks> + /// Remove's to the origin dictionary + /// </remarks> + bool RemoveOrigin(TKeyOrigin key); + + /// <inheritdoc cref="Dictionary{TKey,TValue}.Clear" /> + /// <remarks> + /// Clear's to the origin dictionary + /// </remarks> + void ClearOrigin(); + } + /// <inheritdoc /> public class ObservableDictionary<TKey, TValue> : IObservableDictionary<TKey, TValue> { @@ -153,7 +223,7 @@ public bool ContainsKey(TKey key) } /// <inheritdoc /> - public void Add(TKey key, TValue value) + public virtual void Add(TKey key, TValue value) { Dictionary.Add(key, value); @@ -172,7 +242,7 @@ public void Add(TKey key, TValue value) } /// <inheritdoc /> - public bool Remove(TKey key) + public virtual bool Remove(TKey key) { if (!Dictionary.TryGetValue(key, out var value)) { @@ -197,6 +267,22 @@ public bool Remove(TKey key) return true; } + /// <inheritdoc /> + public virtual void Clear() + { + var dictionary = new Dictionary<TKey, TValue>(Dictionary); + + Dictionary.Clear(); + + for (var i = 0; i < _updateActions.Count; i++) + { + foreach (var data in dictionary) + { + _updateActions[i](data.Key, data.Value, default, ObservableUpdateType.Removed); + } + } + } + /// <inheritdoc /> public void InvokeUpdate(TKey key) { @@ -310,16 +396,100 @@ protected void InvokeUpdate(TKey key, TValue previousValue) } /// <inheritdoc /> - public class ObservableResolverDictionary<TKey, TValue> : ObservableDictionary<TKey, TValue> - where TValue : struct + public class ObservableResolverDictionary<TKey, TValue, TKeyOrigin, TValueOrigin> : + ObservableDictionary<TKey, TValue>, + IObservableResolverDictionary<TKey, TValue, TKeyOrigin, TValueOrigin> { - private readonly Func<IDictionary<TKey, TValue>> _dictionaryResolver; + private readonly IDictionary<TKeyOrigin, TValueOrigin> _dictionary; + private readonly Func<TKey, TValue, KeyValuePair<TKeyOrigin, TValueOrigin>> _toOrignResolver; + private readonly Func<KeyValuePair<TKeyOrigin, TValueOrigin>, KeyValuePair<TKey, TValue>> _fromOrignResolver; - protected override IDictionary<TKey, TValue> Dictionary => _dictionaryResolver(); + /// <inheritdoc /> + public ReadOnlyDictionary<TKeyOrigin, TValueOrigin> OriginDictionary => new ReadOnlyDictionary<TKeyOrigin, TValueOrigin>(_dictionary); - public ObservableResolverDictionary(Func<IDictionary<TKey, TValue>> dictionaryResolver) + public ObservableResolverDictionary(IDictionary<TKeyOrigin, TValueOrigin> dictionary, + Func<KeyValuePair<TKeyOrigin, TValueOrigin>, KeyValuePair<TKey, TValue>> fromOrignResolver, + Func<TKey, TValue, KeyValuePair<TKeyOrigin, TValueOrigin>> toOrignResolver) + : base(new Dictionary<TKey, TValue>(dictionary.Count)) + { + _dictionary = dictionary; + _toOrignResolver = toOrignResolver; + _fromOrignResolver = fromOrignResolver; + + foreach (var pair in dictionary) + { + Dictionary.Add(fromOrignResolver(pair)); + } + } + + /// <inheritdoc /> + public TValueOrigin GetOriginValue(TKey key) + { + return _dictionary[_toOrignResolver(key, default).Key]; + } + + /// <inheritdoc /> + public bool TryGetOriginValue(TKey key, out TValueOrigin value) + { + return _dictionary.TryGetValue(_toOrignResolver(key, default).Key, out value); + } + + /// <inheritdoc /> + public void UpdateOrigin(TKeyOrigin key, TValueOrigin value) + { + var convertPair = _fromOrignResolver(new KeyValuePair<TKeyOrigin, TValueOrigin>(key, value)); + + _dictionary[key] = value; + this[convertPair.Key] = convertPair.Value; + } + + /// <inheritdoc /> + public override void Add(TKey key, TValue value) + { + _dictionary.Add(_toOrignResolver(key, value)); + base.Add(key, value); + } + + /// <inheritdoc /> + public override bool Remove(TKey key) + { + var pair = _toOrignResolver(key, Dictionary[key]); + + _dictionary.Remove(pair.Key); + + return base.Remove(key); + } + + /// <inheritdoc /> + public override void Clear() + { + _dictionary.Clear(); + base.Clear(); ; + } + + /// <inheritdoc /> + public void AddOrigin(TKeyOrigin key, TValueOrigin value) + { + var convertPair = _fromOrignResolver(new KeyValuePair<TKeyOrigin, TValueOrigin>(key, value)); + + _dictionary.Add(key, value); + base.Add(convertPair.Key, convertPair.Value); + } + + /// <inheritdoc /> + public bool RemoveOrigin(TKeyOrigin key) + { + var convertPair = _fromOrignResolver(new KeyValuePair<TKeyOrigin, TValueOrigin>(key, OriginDictionary[key])); + + _dictionary.Remove(key); + return base.Remove(convertPair.Key); + } + + /// <inheritdoc /> + public void ClearOrigin() { - _dictionaryResolver = dictionaryResolver; + _dictionary.Clear(); + base.Clear(); } } } \ No newline at end of file diff --git a/Runtime/ObservableList.cs b/Runtime/ObservableList.cs index f6e39bb..354278a 100644 --- a/Runtime/ObservableList.cs +++ b/Runtime/ObservableList.cs @@ -1,6 +1,8 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Linq; +using System.Reflection; // ReSharper disable once CheckNamespace @@ -70,11 +72,11 @@ public interface IObservableList<T> : IObservableListReader<T> /// </summary> new T this[int index] { get; set; } - /// <inheritdoc cref="List{T}.Remove"/> + /// <inheritdoc cref="List{T}.Add"/> void Add(T data); /// <inheritdoc cref="List{T}.Remove"/> - void Remove(T data); + bool Remove(T data); /// <inheritdoc cref="List{T}.RemoveAt"/> void RemoveAt(int index); @@ -88,6 +90,52 @@ public interface IObservableList<T> : IObservableListReader<T> void InvokeUpdate(int index); } + /// <inheritdoc /> + /// <remarks> + /// This interface resolves between 2 lists with different types of values + /// </remarks> + public interface IObservableResolverListReader<T, TOrigin> : IObservableListReader<T> + { + /// <summary> + /// The Original List that is being resolved across the entire interface + /// </summary> + IReadOnlyList<TOrigin> OriginList { get; } + } + + /// <inheritdoc /> + /// <remarks> + /// This interface resolves between 2 lists with different types of values + /// </remarks> + public interface IObservableResolverList<T, TOrigin> : + IObservableResolverListReader<T, TOrigin>, + IObservableList<T> + { + /// <summary> + /// Updates the value in the origin list corresponding to the specified index. + /// </summary> + /// <param name="index">The index of the value to update in the origin list.</param> + /// <param name="value">The new value to set in the origin list.</param> + void UpdateOrigin(TOrigin value, int index); + + /// <inheritdoc cref="List{T}.Add"/> + /// <remarks> + /// Add's the value to the origin list + /// </remarks> + void AddOrigin(TOrigin value); + + /// <inheritdoc cref="List{T}.Remove"/> + /// <remarks> + /// Remove's the value to the origin list + /// </remarks> + bool RemoveOrigin(TOrigin value); + + /// <inheritdoc cref="List{T}.Clear"/> + /// <remarks> + /// Clear's to the origin list + /// </remarks> + void ClearOrigin(); + } + /// <inheritdoc /> public class ObservableList<T> : IObservableList<T> { @@ -110,15 +158,15 @@ public T this[int index] /// <inheritdoc /> public int Count => List.Count; /// <inheritdoc /> - public IReadOnlyList<T> ReadOnlyList => List; + public IReadOnlyList<T> ReadOnlyList => new List<T>(List); protected virtual List<T> List { get; } protected ObservableList() { } - public ObservableList(List<T> list) + public ObservableList(IList<T> list) { - List = list; + List = list as List<T> ?? list.ToList(); } /// <inheritdoc cref="List{T}.GetEnumerator"/> @@ -152,7 +200,7 @@ public int IndexOf(T value) } /// <inheritdoc /> - public void Add(T data) + public virtual void Add(T data) { List.Add(data); @@ -163,18 +211,22 @@ public void Add(T data) } /// <inheritdoc /> - public void Remove(T data) + public bool Remove(T data) { var idx = List.IndexOf(data); if (idx >= 0) { RemoveAt(idx); + + return true; } + + return false; } /// <inheritdoc /> - public void RemoveAt(int index) + public virtual void RemoveAt(int index) { var data = List[index]; @@ -187,17 +239,17 @@ public void RemoveAt(int index) } /// <inheritdoc /> - public void Clear() + public virtual void Clear() { - var data = new List<T>(List); + var list = new List<T>(List); List.Clear(); for (var i = 0; i < _updateActions.Count; i++) { - for (var j = 0; j < data.Count; j++) + for (var j = 0; j < list.Count; j++) { - _updateActions[i](j, data[j], default, ObservableUpdateType.Removed); + _updateActions[i](j, list[j], default, ObservableUpdateType.Removed); } } } @@ -257,15 +309,78 @@ protected void InvokeUpdate(int index, T previousValue) } /// <inheritdoc /> - public class ObservableResolverList<T> : ObservableList<T> + public class ObservableResolverList<T, TOrigin> : ObservableList<T>, IObservableResolverList<T, TOrigin> { - private readonly Func<List<T>> _listResolver; + private readonly IList<TOrigin> _originList; + private readonly Func<TOrigin, T> _fromOrignResolver; + private readonly Func<T, TOrigin> _toOrignResolver; - protected override List<T> List => _listResolver(); + /// <inheritdoc /> + public IReadOnlyList<TOrigin> OriginList => new List<TOrigin>(_originList); - public ObservableResolverList(Func<List<T>> listResolver) + public ObservableResolverList(IList<TOrigin> originList, + Func<TOrigin, T> fromOrignResolver, + Func<T, TOrigin> toOrignResolver) : + base(new List<T>(originList.Count)) + { + _originList = originList; + _fromOrignResolver = fromOrignResolver; + _toOrignResolver = toOrignResolver; + + for (var i = 0; i < originList.Count; i++) + { + List.Add(fromOrignResolver(originList[i])); + } + } + + /// <inheritdoc /> + public override void Add(T data) + { + _originList.Add(_toOrignResolver(data)); + base.Add(data); + } + + /// <inheritdoc /> + public override void RemoveAt(int index) + { + _originList.RemoveAt(index); + base.RemoveAt(index); + } + + /// <inheritdoc /> + public override void Clear() + { + _originList.Clear(); + base.Clear(); + } + + /// <inheritdoc /> + public void UpdateOrigin(TOrigin value, int index) + { + _originList[index] = value; + List[index] = _fromOrignResolver(value); + } + + /// <inheritdoc /> + public void AddOrigin(TOrigin value) + { + _originList.Add(value); + List.Add(_fromOrignResolver(value)); + } + + /// <inheritdoc /> + public bool RemoveOrigin(TOrigin value) + { + _originList.Remove(value); + + return base.Remove(_fromOrignResolver(value)); + } + + /// <inheritdoc /> + public void ClearOrigin() { - _listResolver = listResolver; + _originList.Clear(); + base.Clear(); } } } \ No newline at end of file diff --git a/Tests/Editor/OberservableResolverListTest.cs b/Tests/Editor/OberservableResolverListTest.cs new file mode 100644 index 0000000..453f248 --- /dev/null +++ b/Tests/Editor/OberservableResolverListTest.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Reflection; +using GameLovers; +using NSubstitute; +using NUnit.Framework; + +// ReSharper disable once CheckNamespace + +namespace GameLoversEditor.DataExtensions.Tests +{ + [TestFixture] + public class ObservableResolverListTest + { + private int _index = 0; + private IObservableResolverList<int, string> _list; + private IList<string> _mockList; + + [SetUp] + public void SetUp() + { + _mockList = Substitute.For<IList<string>>(); + _list = new ObservableResolverList<int, string>(_mockList, + origin => int.Parse(origin), + value => value.ToString()); + } + + [Test] + public void AddOrigin_AddsValueToOriginList() + { + var value = "1"; + + _list.AddOrigin(value); + + _mockList.Received().Add(value); + } + + [Test] + public void UpdateOrigin_UpdatesOriginList() + { + var value = "1"; + + _list.AddOrigin(value); + _list.UpdateOrigin(value, _index); + + _mockList.Received()[_index] = value; + } + + [Test] + public void RemoveOrigin_RemovesValueFromOriginList() + { + var value = "1"; + + _list.AddOrigin(value); + + Assert.IsTrue(_list.RemoveOrigin(value)); + _mockList.Received().Remove(value); + } + + [Test] + public void ClearOrigin_ClearsOriginList() + { + _list.ClearOrigin(); + + _mockList.Received().Clear(); + } + } +} \ No newline at end of file diff --git a/Tests/Editor/OberservableResolverListTest.cs.meta b/Tests/Editor/OberservableResolverListTest.cs.meta new file mode 100644 index 0000000..7e1207b --- /dev/null +++ b/Tests/Editor/OberservableResolverListTest.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 339332fedbfe038408ad12655029d0a1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tests/Editor/ObservableDictionaryTest.cs b/Tests/Editor/ObservableDictionaryTest.cs index 23ece15..f62a2a0 100644 --- a/Tests/Editor/ObservableDictionaryTest.cs +++ b/Tests/Editor/ObservableDictionaryTest.cs @@ -1,7 +1,9 @@ +using System; using System.Collections.Generic; using GameLovers; using NSubstitute; using NUnit.Framework; +using UnityEngine; // ReSharper disable once CheckNamespace @@ -11,8 +13,6 @@ namespace GameLoversEditor.DataExtensions.Tests public class ObservableDictionaryTest { private const int _key = 0; - private const int _previousValue = 5; - private const int _newValue = 10; /// <summary> /// Mocking interface to check method calls received @@ -22,8 +22,7 @@ public interface IMockCaller<in TKey, in TValue> void Call(TKey key, TValue previousValue, TValue newValue, ObservableUpdateType updateType); } - private ObservableDictionary<int, int> _observableDictionary; - private ObservableResolverDictionary<int, int> _observableResolverDictionary; + private ObservableDictionary<int, int> _dictionary; private IDictionary<int, int> _mockDictionary; private IMockCaller<int, int> _caller; @@ -31,110 +30,176 @@ public interface IMockCaller<in TKey, in TValue> public void Init() { _caller = Substitute.For<IMockCaller<int, int>>(); - _mockDictionary = Substitute.For<IDictionary<int, int>>(); - _observableDictionary = new ObservableDictionary<int, int>(_mockDictionary); - _observableResolverDictionary = new ObservableResolverDictionary<int, int>(() => _mockDictionary); + _mockDictionary = new Dictionary<int, int>(); + _dictionary = new ObservableDictionary<int, int>(_mockDictionary); + } + + [Test] + public void TryGetValue_ReturnsFalse_WhenKeyDoesNotExist() + { + bool result = _dictionary.TryGetValue(1, out int value); - _mockDictionary.TryGetValue(_key, out _).Returns(callInfo => - { - callInfo[1] = _mockDictionary[_key]; - return true; - }); + Assert.IsFalse(result); } [Test] - public void ValueCheck() + public void TryGetValue_ReturnsTrue_WhenKeyExists() { - _mockDictionary[_key].Returns(_previousValue); + _dictionary.Add(1, 100); - Assert.AreEqual(_previousValue, _observableDictionary[_key]); - Assert.AreEqual(_previousValue, _observableResolverDictionary[_key]); + bool result = _dictionary.TryGetValue(1, out int value); + + Assert.IsTrue(result); + Assert.AreEqual(100, value); } [Test] - public void ValueSetCheck() + public void ContainsKey_ReturnsFalse_WhenKeyDoesNotExist() { - const int valueCheck1 = 5; - const int valueCheck2 = 6; - const int valueCheck3 = 7; + Assert.IsFalse(_dictionary.ContainsKey(1)); + } - _mockDictionary[_key] = valueCheck1; + [Test] + public void ContainsKey_ReturnsTrue_WhenKeyExists() + { + _dictionary.Add(1, 100); - Assert.AreEqual(valueCheck1, _observableDictionary[_key]); - Assert.AreEqual(valueCheck1, _observableResolverDictionary[_key]); + Assert.IsTrue(_dictionary.ContainsKey(1)); + } - _observableDictionary[_key] = valueCheck2; + [Test] + public void Indexer_ReturnsValue_WhenKeyExists() + { + _dictionary.Add(1, 100); - Assert.AreEqual(valueCheck2, _observableDictionary[_key]); - Assert.AreEqual(valueCheck2, _observableResolverDictionary[_key]); + Assert.AreEqual(100, _dictionary[1]); + } - _observableResolverDictionary[_key] = valueCheck3; + [Test] + public void Indexer_SetsValue_WhenKeyExists() + { + _dictionary.Add(1, 100); + _dictionary[1] = 200; - Assert.AreEqual(valueCheck3, _observableDictionary[_key]); - Assert.AreEqual(valueCheck3, _observableResolverDictionary[_key]); + Assert.AreEqual(200, _dictionary[1]); } [Test] - public void ObserveCheck() + public void Add_AddsKeyValuePair_WhenKeyDoesNotExist() { - _observableDictionary.Observe(_key, _caller.Call); - _observableDictionary.Observe(_caller.Call); - _observableResolverDictionary.Observe(_key, _caller.Call); - _observableResolverDictionary.Observe(_caller.Call); + _dictionary.Add(1, 100); - // _caller.DidNotReceive().Call(Arg.Any<int>(), Arg.Any<int>(), Arg.Any<ObservableUpdateType>()); + Assert.AreEqual(100, _dictionary[1]); + } - _observableDictionary.Add(_key, _previousValue); - _observableResolverDictionary.Add(_key, _previousValue); + [Test] + public void Add_ThrowsException_WhenKeyAlreadyExists() + { + _dictionary.Add(1, 100); - _mockDictionary[_key].Returns(_previousValue); + Assert.Throws<ArgumentException>(() => _dictionary.Add(1, 200)); + } - _observableDictionary[_key] = _newValue; + [Test] + public void Remove_RemovesKeyValuePair_WhenKeyExists() + { + _dictionary.Add(1, 100); - _mockDictionary[_key].Returns(_previousValue); + Assert.IsTrue(_dictionary.Remove(1)); + Assert.AreEqual(0, _dictionary.Count); + } - _observableResolverDictionary[_key] = _newValue; + [Test] + public void Remove_ReturnsFalse_WhenKeyDoesNotExist() + { + Assert.IsFalse(_dictionary.Remove(1)); + } - _observableDictionary.Remove(_key); - _observableResolverDictionary.Remove(_key); + [Test] + public void Clear_RemovesAllKeyValuePairs() + { + _dictionary.Add(1, 100); + _dictionary.Add(2, 200); + _dictionary.Clear(); - _caller.Received(4).Call(_key, 0, _previousValue, ObservableUpdateType.Added); - _caller.Received(4).Call(_key, _previousValue, _newValue, ObservableUpdateType.Updated); - _caller.Received(4).Call(_key, _newValue, 0, ObservableUpdateType.Removed); + Assert.AreEqual(0, _dictionary.Count); + } + + [Test] + public void ValueSetCheck() + { + const int valueCheck1 = 5; + const int valueCheck2 = 6; + + _mockDictionary.Add(_key, valueCheck1); + _dictionary[_key] = valueCheck2; + + Assert.AreNotEqual(valueCheck1, _mockDictionary[_key]); + Assert.AreEqual(valueCheck2, _dictionary[_key]); + } + + [Test] + public void ObserveCheck() + { + var startValue = 0; + var newValue = 1; + + _dictionary.Observe(_key, _caller.Call); + _dictionary.Observe(_caller.Call); + + _dictionary.Add(_key, startValue); + + _dictionary[_key] = newValue; + + _dictionary.Remove(_key); + + _caller.Received().Call(_key, 0, startValue, ObservableUpdateType.Added); + _caller.Received().Call(_key, startValue, newValue, ObservableUpdateType.Updated); + _caller.Received().Call(_key, newValue, 0, ObservableUpdateType.Removed); } [Test] public void InvokeObserveCheck() { - _observableDictionary.InvokeObserve(_key, _caller.Call); - _observableResolverDictionary.InvokeObserve(_key, _caller.Call); + _dictionary.Add(_key, 0); + _dictionary.InvokeObserve(_key, _caller.Call); _caller.DidNotReceive().Call(Arg.Any<int>(), Arg.Any<int>(), Arg.Any<int>(), ObservableUpdateType.Added); - _caller.Received(2).Call(_key, 0, 0, ObservableUpdateType.Updated); + _caller.Received().Call(_key, 0, 0, ObservableUpdateType.Updated); _caller.DidNotReceive().Call(Arg.Any<int>(), Arg.Any<int>(), Arg.Any<int>(), ObservableUpdateType.Removed); } [Test] - public void InvokeCheck() + public void InvokeUpdate_MissingKey_ThrowsException() + { + Assert.Throws<KeyNotFoundException>(() => _dictionary.InvokeUpdate(_key)); + } + + [Test] + public void InvokeObserve_MissingKey_ThrowsException() { - _observableDictionary.Observe(_key, _caller.Call); - _observableDictionary.Observe(_caller.Call); - _observableResolverDictionary.Observe(_key, _caller.Call); - _observableResolverDictionary.Observe(_caller.Call); + Assert.Throws<KeyNotFoundException>(() => _dictionary.InvokeObserve(_key, _caller.Call)); + } - _observableDictionary.InvokeUpdate(_key); - _observableResolverDictionary.InvokeUpdate(_key); + [Test] + public void InvokeUpdateCheck() + { + _dictionary.Add(_key, 0); + _dictionary.Observe(_key, _caller.Call); + _dictionary.Observe(_caller.Call); + + _dictionary.InvokeUpdate(_key); _caller.DidNotReceive().Call(Arg.Any<int>(), Arg.Any<int>(), Arg.Any<int>(), ObservableUpdateType.Added); - _caller.Received(4).Call(_key, 0, 0, ObservableUpdateType.Updated); + _caller.Received(2).Call(_key, 0, 0, ObservableUpdateType.Updated); _caller.DidNotReceive().Call(Arg.Any<int>(), Arg.Any<int>(), Arg.Any<int>(), ObservableUpdateType.Removed); } [Test] - public void InvokeCheck_NotObserving_DoesNothing() + public void InvokeUpdate_NotObserving_DoesNothing() { - _observableDictionary.InvokeUpdate(_key); - _observableResolverDictionary.InvokeUpdate(_key); + _dictionary.Add(_key, 0); + _dictionary.InvokeUpdate(_key); _caller.DidNotReceive().Call(Arg.Any<int>(), Arg.Any<int>(), Arg.Any<int>(), Arg.Any<ObservableUpdateType>()); } @@ -142,17 +207,12 @@ public void InvokeCheck_NotObserving_DoesNothing() [Test] public void StopObserveCheck() { - _observableDictionary.Observe(_caller.Call); - _observableResolverDictionary.Observe(_caller.Call); - _observableDictionary.StopObserving(_caller.Call); - _observableResolverDictionary.StopObserving(_caller.Call); + _dictionary.Observe(_caller.Call); + _dictionary.StopObserving(_caller.Call); - _observableDictionary.Add(_key, _previousValue); - _observableResolverDictionary.Add(_key, _previousValue); - _observableDictionary[_key] = _previousValue; - _observableResolverDictionary[_key] = _previousValue; - _observableDictionary.Remove(_key); - _observableResolverDictionary.Remove(_key); + _dictionary.Add(_key, 0); + _dictionary[_key] = 0; + _dictionary.Remove(_key); _caller.DidNotReceive().Call(Arg.Any<int>(), Arg.Any<int>(), Arg.Any<int>(), Arg.Any<ObservableUpdateType>()); } @@ -160,17 +220,12 @@ public void StopObserveCheck() [Test] public void StopObserve_KeyCheck() { - _observableDictionary.Observe(_key, _caller.Call); - _observableResolverDictionary.Observe(_key, _caller.Call); - _observableDictionary.StopObserving(_key); - _observableResolverDictionary.StopObserving(_key); + _dictionary.Observe(_key, _caller.Call); + _dictionary.StopObserving(_key); - _observableDictionary.Add(_key, _previousValue); - _observableResolverDictionary.Add(_key, _previousValue); - _observableDictionary[_key] = _previousValue; - _observableResolverDictionary[_key] = _previousValue; - _observableDictionary.Remove(_key); - _observableResolverDictionary.Remove(_key); + _dictionary.Add(_key, 0); + _dictionary[_key] = 0; + _dictionary.Remove(_key); _caller.DidNotReceive().Call(Arg.Any<int>(), Arg.Any<int>(), Arg.Any<int>(), Arg.Any<ObservableUpdateType>()); } @@ -178,17 +233,12 @@ public void StopObserve_KeyCheck() [Test] public void StopObservingAllCheck() { - _observableDictionary.Observe(_caller.Call); - _observableResolverDictionary.Observe(_caller.Call); - _observableDictionary.StopObservingAll(_caller); - _observableResolverDictionary.StopObservingAll(_caller); + _dictionary.Observe(_caller.Call); + _dictionary.StopObservingAll(_caller); - _observableDictionary.Add(_key, _previousValue); - _observableResolverDictionary.Add(_key, _previousValue); - _observableDictionary[_key] = _previousValue; - _observableResolverDictionary[_key] = _previousValue; - _observableDictionary.Remove(_key); - _observableResolverDictionary.Remove(_key); + _dictionary.Add(_key, 0); + _dictionary[_key] = 0; + _dictionary.Remove(_key); _caller.DidNotReceive().Call(Arg.Any<int>(), Arg.Any<int>(), Arg.Any<int>(), Arg.Any<ObservableUpdateType>()); } @@ -196,19 +246,13 @@ public void StopObservingAllCheck() [Test] public void StopObservingAll_MultipleCalls_Check() { - _observableDictionary.Observe(_caller.Call); - _observableDictionary.Observe(_caller.Call); - _observableResolverDictionary.Observe(_caller.Call); - _observableResolverDictionary.Observe(_caller.Call); - _observableDictionary.StopObservingAll(_caller); - _observableResolverDictionary.StopObservingAll(_caller); + _dictionary.Observe(_caller.Call); + _dictionary.Observe(_caller.Call); + _dictionary.StopObservingAll(_caller); - _observableDictionary.Add(_key, _previousValue); - _observableResolverDictionary.Add(_key, _previousValue); - _observableDictionary[_key] = _previousValue; - _observableResolverDictionary[_key] = _previousValue; - _observableDictionary.Remove(_key); - _observableResolverDictionary.Remove(_key); + _dictionary.Add(_key, 0); + _dictionary[_key] = 0; + _dictionary.Remove(_key); _caller.DidNotReceive().Call(Arg.Any<int>(), Arg.Any<int>(), Arg.Any<int>(), Arg.Any<ObservableUpdateType>()); } @@ -216,17 +260,12 @@ public void StopObservingAll_MultipleCalls_Check() [Test] public void StopObservingAll_Everything_Check() { - _observableDictionary.Observe(_caller.Call); - _observableResolverDictionary.Observe(_caller.Call); - _observableDictionary.StopObservingAll(); - _observableResolverDictionary.StopObservingAll(); + _dictionary.Observe(_caller.Call); + _dictionary.StopObservingAll(); - _observableDictionary.Add(_key, _previousValue); - _observableResolverDictionary.Add(_key, _previousValue); - _observableDictionary[_key] = _previousValue; - _observableResolverDictionary[_key] = _previousValue; - _observableDictionary.Remove(_key); - _observableResolverDictionary.Remove(_key); + _dictionary.Add(_key, 0); + _dictionary[_key] = 0; + _dictionary.Remove(_key); _caller.DidNotReceive().Call(Arg.Any<int>(), Arg.Any<int>(), Arg.Any<int>(), Arg.Any<ObservableUpdateType>()); } @@ -234,15 +273,11 @@ public void StopObservingAll_Everything_Check() [Test] public void StopObservingAll_NotObserving_DoesNothing() { - _observableDictionary.StopObservingAll(_caller); - _observableResolverDictionary.StopObservingAll(_caller); + _dictionary.StopObservingAll(_caller); - _observableDictionary.Add(_key, _previousValue); - _observableResolverDictionary.Add(_key, _previousValue); - _observableDictionary[_key] = _previousValue; - _observableResolverDictionary[_key] = _previousValue; - _observableDictionary.Remove(_key); - _observableResolverDictionary.Remove(_key); + _dictionary.Add(_key, 0); + _dictionary[_key] = 0; + _dictionary.Remove(_key); _caller.DidNotReceive().Call(Arg.Any<int>(), Arg.Any<int>(), Arg.Any<int>(), Arg.Any<ObservableUpdateType>()); } diff --git a/Tests/Editor/ObservableListTest.cs b/Tests/Editor/ObservableListTest.cs index caa312d..be9b939 100644 --- a/Tests/Editor/ObservableListTest.cs +++ b/Tests/Editor/ObservableListTest.cs @@ -22,74 +22,57 @@ public interface IMockCaller<in T> private const int _previousValue = 5; private const int _newValue = 10; - private ObservableList<int> _observableList; - private ObservableResolverList<int> _observableResolverList; - private List<int> _list; + private ObservableList<int> _list; + private IList<int> _mockList; private IMockCaller<int> _caller; [SetUp] public void Init() { _caller = Substitute.For<IMockCaller<int>>(); - _list = new List<int>(); - _observableList = new ObservableList<int>(_list); - _observableResolverList = new ObservableResolverList<int>(() => _list); + _mockList = Substitute.For<IList<int>>(); + _list = new ObservableList<int>(_mockList); } [Test] - public void ValueCheck() + public void AddValue_AddsValueToList() { _list.Add(_previousValue); - Assert.AreEqual(_previousValue, _observableList[_index]); - Assert.AreEqual(_previousValue, _observableResolverList[_index]); + Assert.AreEqual(_previousValue, _list[_index]); } [Test] - public void ValueSetCheck() + public void SetValue_UpdatesValue() { const int valueCheck1 = 5; const int valueCheck2 = 6; - const int valueCheck3 = 7; _list.Add(valueCheck1); - Assert.AreEqual(valueCheck1, _observableList[_index]); - Assert.AreEqual(valueCheck1, _observableResolverList[_index]); + Assert.AreEqual(valueCheck1, _list[_index]); - _observableList[_index] = valueCheck2; + _list[_index] = valueCheck2; - Assert.AreEqual(valueCheck2, _observableList[_index]); - Assert.AreEqual(valueCheck2, _observableResolverList[_index]); - - _observableResolverList[_index] = valueCheck3; - - Assert.AreEqual(valueCheck3, _observableList[_index]); - Assert.AreEqual(valueCheck3, _observableResolverList[_index]); + Assert.AreEqual(valueCheck2, _list[_index]); } [Test] public void ObserveCheck() { - _observableList.Observe(_caller.Call); - _observableResolverList.Observe(_caller.Call); + _list.Observe(_caller.Call); _caller.DidNotReceive().Call(Arg.Any<int>(), Arg.Any<int>(), Arg.Any<int>(), Arg.Any<ObservableUpdateType>()); - _observableList.Add(_previousValue); - _observableResolverList.Add(_previousValue); - - _observableList[_index] = _newValue; - _list[_index] = _previousValue; - _observableResolverList[_index] = _newValue; + _list.Add(_previousValue); - _observableList.RemoveAt(_index); _list[_index] = _newValue; - _observableResolverList.RemoveAt(_index); - _caller.Received(2).Call(Arg.Any<int>(), Arg.Is(0), Arg.Is(_previousValue), ObservableUpdateType.Added); - _caller.Received(2).Call(_index, _previousValue, _newValue, ObservableUpdateType.Updated); - _caller.Received(2).Call(_index, _newValue, 0, ObservableUpdateType.Removed); + _list.RemoveAt(_index); + + _caller.Received().Call(Arg.Any<int>(), Arg.Is(0), Arg.Is(_previousValue), ObservableUpdateType.Added); + _caller.Received().Call(_index, _previousValue, _newValue, ObservableUpdateType.Updated); + _caller.Received().Call(_index, _newValue, 0, ObservableUpdateType.Removed); } [Test] @@ -97,11 +80,10 @@ public void InvokeObserveCheck() { _list.Add(_previousValue); - _observableList.InvokeObserve(_index, _caller.Call); - _observableResolverList.InvokeObserve(_index, _caller.Call); + _list.InvokeObserve(_index, _caller.Call); _caller.DidNotReceive().Call(_index, _previousValue, _previousValue, ObservableUpdateType.Added); - _caller.Received(2).Call(_index, _previousValue, _previousValue, ObservableUpdateType.Updated); + _caller.Received().Call(_index, _previousValue, _previousValue, ObservableUpdateType.Updated); _caller.DidNotReceive().Call(_index, _previousValue, _previousValue, ObservableUpdateType.Removed); } @@ -109,17 +91,14 @@ public void InvokeObserveCheck() public void InvokeCheck() { _list.Add(_previousValue); - - _observableList.Observe(_caller.Call); - _observableResolverList.Observe(_caller.Call); + _list.Observe(_caller.Call); _caller.DidNotReceive().Call(Arg.Any<int>(), Arg.Any<int>(), Arg.Any<int>(), Arg.Any<ObservableUpdateType>()); - _observableList.InvokeUpdate(_index); - _observableResolverList.InvokeUpdate(_index); + _list.InvokeUpdate(_index); _caller.DidNotReceive().Call(Arg.Any<int>(), Arg.Any<int>(), Arg.Any<int>(), ObservableUpdateType.Added); - _caller.Received(2).Call(_index, _previousValue, _previousValue, ObservableUpdateType.Updated); + _caller.Received().Call(_index, _previousValue, _previousValue, ObservableUpdateType.Updated); _caller.DidNotReceive().Call(Arg.Any<int>(), Arg.Any<int>(), Arg.Any<int>(), ObservableUpdateType.Removed); } @@ -127,9 +106,7 @@ public void InvokeCheck() public void InvokeCheck_NotObserving_DoesNothing() { _list.Add(_previousValue); - - _observableList.InvokeUpdate(_index); - _observableResolverList.InvokeUpdate(_index); + _list.InvokeUpdate(_index); _caller.DidNotReceive().Call(Arg.Any<int>(), Arg.Any<int>(), Arg.Any<int>(), Arg.Any<ObservableUpdateType>()); } @@ -137,17 +114,13 @@ public void InvokeCheck_NotObserving_DoesNothing() [Test] public void StopObserveCheck() { - _observableList.Observe(_caller.Call); - _observableResolverList.Observe(_caller.Call); - _observableList.StopObserving(_caller.Call); - _observableResolverList.StopObserving(_caller.Call); - - _observableList.Add(_previousValue); - _observableResolverList.Add(_previousValue); - _observableList[_index] = _previousValue; - _observableResolverList[_index] = _previousValue; - _observableList.RemoveAt(_index); - _observableResolverList.RemoveAt(_index); + _list.Observe(_caller.Call); + _list.StopObserving(_caller.Call); + _list.Add(_previousValue); + + _list[_index] = _previousValue; + + _list.RemoveAt(_index); _caller.DidNotReceive().Call(Arg.Any<int>(), Arg.Any<int>(), Arg.Any<int>(), Arg.Any<ObservableUpdateType>()); } @@ -155,15 +128,10 @@ public void StopObserveCheck() [Test] public void StopObservingAllCheck() { - _observableList.Observe(_caller.Call); - _observableResolverList.Observe(_caller.Call); - _observableList.StopObservingAll(_caller); - _observableResolverList.StopObservingAll(_caller); - - _observableList.Add(_previousValue); - _observableResolverList.Add(_previousValue); - _observableList.InvokeUpdate(_index); - _observableResolverList.InvokeUpdate(_index); + _list.Observe(_caller.Call); + _list.StopObservingAll(_caller); + _list.Add(_previousValue); + _list.InvokeUpdate(_index); _caller.DidNotReceive().Call(Arg.Any<int>(), Arg.Any<int>(), Arg.Any<int>(), Arg.Any<ObservableUpdateType>()); } @@ -171,17 +139,11 @@ public void StopObservingAllCheck() [Test] public void StopObservingAll_MultipleCalls_Check() { - _observableList.Observe(_caller.Call); - _observableList.Observe(_caller.Call); - _observableResolverList.Observe(_caller.Call); - _observableResolverList.Observe(_caller.Call); - _observableList.StopObservingAll(_caller); - _observableResolverList.StopObservingAll(_caller); - - _observableList.Add(_previousValue); - _observableResolverList.Add(_previousValue); - _observableList.InvokeUpdate(_index); - _observableResolverList.InvokeUpdate(_index); + _list.Observe(_caller.Call); + _list.Observe(_caller.Call); + _list.StopObservingAll(_caller); + _list.Add(_previousValue); + _list.InvokeUpdate(_index); _caller.DidNotReceive().Call(Arg.Any<int>(), Arg.Any<int>(), Arg.Any<int>(), Arg.Any<ObservableUpdateType>()); } @@ -189,15 +151,11 @@ public void StopObservingAll_MultipleCalls_Check() [Test] public void StopObservingAll_Everything_Check() { - _observableList.Observe(_caller.Call); - _observableResolverList.Observe(_caller.Call); - _observableList.StopObservingAll(); - _observableResolverList.StopObservingAll(); + _list.Observe(_caller.Call); + _list.StopObservingAll(); - _observableList.Add(_previousValue); - _observableResolverList.Add(_previousValue); - _observableList.InvokeUpdate(_index); - _observableResolverList.InvokeUpdate(_index); + _list.Add(_previousValue); + _list.InvokeUpdate(_index); _caller.DidNotReceive().Call(Arg.Any<int>(), Arg.Any<int>(), Arg.Any<int>(), Arg.Any<ObservableUpdateType>()); } @@ -205,13 +163,10 @@ public void StopObservingAll_Everything_Check() [Test] public void StopObservingAll_NotObserving_DoesNothing() { - _observableList.StopObservingAll(); - _observableResolverList.StopObservingAll(); + _list.StopObservingAll(); - _observableList.Add(_previousValue); - _observableResolverList.Add(_previousValue); - _observableList.InvokeUpdate(_index); - _observableResolverList.InvokeUpdate(_index); + _list.Add(_previousValue); + _list.InvokeUpdate(_index); _caller.DidNotReceive().Call(Arg.Any<int>(), Arg.Any<int>(), Arg.Any<int>(), Arg.Any<ObservableUpdateType>()); } diff --git a/Tests/Editor/ObservableResolverDictionaryTest.cs b/Tests/Editor/ObservableResolverDictionaryTest.cs new file mode 100644 index 0000000..d3e7be9 --- /dev/null +++ b/Tests/Editor/ObservableResolverDictionaryTest.cs @@ -0,0 +1,89 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Reflection; +using GameLovers; +using NSubstitute; +using NUnit.Framework; +using UnityEngine; + +// ReSharper disable once CheckNamespace + +namespace GameLoversEditor.DataExtensions.Tests +{ + [TestFixture] + public class ObservableResolverDictionaryTest + { + private int _key = 0; + private string _value = "1"; + private ObservableResolverDictionary<int, int, int, string> _dictionary; + private IDictionary<int, string> _mockDictionary; + + [SetUp] + public void Init() + { + _mockDictionary = Substitute.For<IDictionary<int, string>>(); + _dictionary = new ObservableResolverDictionary<int, int, int, string>( + _mockDictionary, + origin => new KeyValuePair<int, int>(origin.Key, int.Parse(origin.Value)), + (key, value) => new KeyValuePair<int, string>(key, key.ToString())); + + _mockDictionary[_key].Returns(_value); + _mockDictionary.TryGetValue(_key, out _).Returns(callInfo => + { + callInfo[1] = _mockDictionary[_key]; + return true; + }); + } + + [Test] + public void TryGetOriginValue_KeyExists_ReturnsTrueAndOutValue() + { + Assert.IsTrue(_dictionary.TryGetOriginValue(_key, out var value)); + } + + [Test] + public void TryGetOriginValue_KeyDoesNotExist_ReturnsFalseAndOutDefault() + { + var result = _dictionary.TryGetOriginValue(999, out var value); + + Assert.IsFalse(result); + Assert.IsNull(value); + } + + [Test] + public void AddOrigin_AddsValueToOriginDictionary() + { + _dictionary.AddOrigin(_key, _value); + + _mockDictionary.Received().Add(_key, _value); + } + + [Test] + public void UpdateOrigin_UpdatesValueInOriginDictionary() + { + _dictionary.AddOrigin(_key, _value); + _dictionary.UpdateOrigin(_key, _value); + + _mockDictionary.Received()[_key] = _value; + } + + [Test] + public void RemoveOrigin_RemovesValueFromOriginDictionary() + { + _dictionary.AddOrigin(_key, _value); + + Assert.IsTrue(_dictionary.RemoveOrigin(_key)); + _mockDictionary.Received().Remove(_key); + } + + [Test] + public void ClearOrigin_ClearsOriginDictionary() + { + _dictionary.ClearOrigin(); + + _mockDictionary.Received().Clear(); + } + } +} \ No newline at end of file diff --git a/Tests/Editor/ObservableResolverDictionaryTest.cs.meta b/Tests/Editor/ObservableResolverDictionaryTest.cs.meta new file mode 100644 index 0000000..a08312e --- /dev/null +++ b/Tests/Editor/ObservableResolverDictionaryTest.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4caa0f2c6d7acb043a06b1edc62fbb91 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tests/Editor/floatPTests.cs b/Tests/Editor/floatPTests.cs index 95ed1a6..44e9a1a 100644 --- a/Tests/Editor/floatPTests.cs +++ b/Tests/Editor/floatPTests.cs @@ -11,17 +11,16 @@ public class floatPTests [Test] public void Representation() { - Assert.AreEqual(floatP.Zero, 0f); - Assert.AreNotEqual(-floatP.Zero, -0f); + Assert.AreEqual(floatP.Zero, (floatP)0f); + Assert.AreEqual(-floatP.Zero, (floatP) (-0f)); Assert.AreEqual(floatP.Zero, -floatP.Zero); - Assert.AreEqual(floatP.NaN, float.NaN); - Assert.AreEqual(floatP.One, 1f); - Assert.AreEqual(floatP.MinusOne, -1f); - Assert.AreEqual(floatP.PositiveInfinity, float.PositiveInfinity); - Assert.AreEqual(floatP.NegativeInfinity, float.NegativeInfinity); - Assert.AreEqual(floatP.Epsilon, float.Epsilon); - Assert.AreEqual(floatP.MaxValue, float.MaxValue); - Assert.AreEqual(floatP.MinValue, float.MinValue); + Assert.AreEqual(floatP.NaN, (floatP) float.NaN); + Assert.AreEqual(floatP.MinusOne, (floatP) (- 1f)); + Assert.AreEqual(floatP.PositiveInfinity, (floatP)float.PositiveInfinity); + Assert.AreEqual(floatP.NegativeInfinity, (floatP)float.NegativeInfinity); + Assert.AreEqual(floatP.Epsilon, (floatP)float.Epsilon); + Assert.AreEqual(floatP.MaxValue, (floatP)float.MaxValue); + Assert.AreEqual(floatP.MinValue, (floatP)float.MinValue); } [Test] @@ -43,24 +42,24 @@ public void Equality() [Test] public void Addition() { - Assert.AreEqual(floatP.One + floatP.One, 2f); - Assert.AreEqual(floatP.One - floatP.One, 0f); + Assert.AreEqual(floatP.One + floatP.One, (floatP)2f); + Assert.AreEqual(floatP.One - floatP.One, (floatP)0f); } [Test] public void Multiplication() { - Assert.AreEqual(floatP.PositiveInfinity * floatP.Zero, float.PositiveInfinity * 0f); - Assert.AreEqual(floatP.PositiveInfinity * (-floatP.Zero), float.PositiveInfinity * (-0f)); - Assert.AreEqual(floatP.PositiveInfinity * floatP.One, float.PositiveInfinity * 1f); - Assert.AreEqual(floatP.PositiveInfinity * floatP.MinusOne, float.PositiveInfinity * -1f); + Assert.AreEqual(floatP.PositiveInfinity * floatP.Zero, (floatP) (float.PositiveInfinity * 0f)); + Assert.AreEqual(floatP.PositiveInfinity * (-floatP.Zero), (floatP)(float.PositiveInfinity * (-0f))); + Assert.AreEqual(floatP.PositiveInfinity * floatP.One, (floatP)(float.PositiveInfinity * 1f)); + Assert.AreEqual(floatP.PositiveInfinity * floatP.MinusOne, (floatP)(float.PositiveInfinity * -1f)); - Assert.AreEqual(floatP.NegativeInfinity * floatP.Zero, float.NegativeInfinity * 0f); - Assert.AreEqual(floatP.NegativeInfinity * (-floatP.Zero), float.NegativeInfinity * (-0f)); - Assert.AreEqual(floatP.NegativeInfinity * floatP.One, float.NegativeInfinity * 1f); - Assert.AreEqual(floatP.NegativeInfinity * floatP.MinusOne, float.NegativeInfinity * -1f); + Assert.AreEqual(floatP.NegativeInfinity * floatP.Zero, (floatP)(float.NegativeInfinity * 0f)); + Assert.AreEqual(floatP.NegativeInfinity * (-floatP.Zero), (floatP)(float.NegativeInfinity * (-0f))); + Assert.AreEqual(floatP.NegativeInfinity * floatP.One, (floatP)(float.NegativeInfinity * 1f)); + Assert.AreEqual(floatP.NegativeInfinity * floatP.MinusOne, (floatP)(float.NegativeInfinity * -1f)); - Assert.AreEqual(floatP.One * floatP.One, 1f); + Assert.AreEqual(floatP.One * floatP.One, (floatP)1f); } } } diff --git a/package.json b/package.json index 10d2dfc..af7dfed 100644 --- a/package.json +++ b/package.json @@ -2,8 +2,8 @@ "name": "com.gamelovers.dataextensions", "displayName": "Unity Data Type Extensions", "author": "Miguel Tomas", - "version": "0.5.1", - "unity": "2021.4", + "version": "0.6.0", + "unity": "2022.4", "license": "MIT", "description": "This package extends various sets of data types to be used in any type of data containers or persistent serializable data", "type": "library",