From ad385e17ace0fcc423af25cd176314ea0cbe692c Mon Sep 17 00:00:00 2001 From: Jan-Willem Spuij Date: Tue, 26 Nov 2019 17:37:15 +0100 Subject: [PATCH] Convenience methods for unit tests. References #5. --- .../Api/SharedStateObservableExtensions.cs | 23 +++++++ src/Cortex.Net/Cortex.Net.xml | 17 ++++++ src/Cortex.Net/IComputedValue.cs | 7 +++ test/Cortex.Net.Test/Base/ActionTests.cs | 61 +++++++++---------- 4 files changed, 77 insertions(+), 31 deletions(-) diff --git a/src/Cortex.Net/Api/SharedStateObservableExtensions.cs b/src/Cortex.Net/Api/SharedStateObservableExtensions.cs index fb797e8..9433c4e 100644 --- a/src/Cortex.Net/Api/SharedStateObservableExtensions.cs +++ b/src/Cortex.Net/Api/SharedStateObservableExtensions.cs @@ -181,5 +181,28 @@ public static IDictionary Dictionary(this ISharedSta return new ObservableDictionary(sharedState, enhancer, initialValues, name); } + + /// + /// Creates a computed value. + /// + /// The type of the elements. + /// The shared state to operate on. + /// The getter function to use. + /// The name of the observable collection. + /// The computed value. + public static IComputedValue Computed(this ISharedState sharedState, Func getter, string name = null) + { + if (sharedState is null) + { + throw new ArgumentNullException(nameof(sharedState)); + } + + if (string.IsNullOrEmpty(name)) + { + name = $"{nameof(ComputedValue)}@{sharedState.GetUniqueId()}"; + } + + return new ComputedValue(sharedState, new ComputedValueOptions(getter, name)); + } } } diff --git a/src/Cortex.Net/Cortex.Net.xml b/src/Cortex.Net/Cortex.Net.xml index d2440ce..055367d 100644 --- a/src/Cortex.Net/Cortex.Net.xml +++ b/src/Cortex.Net/Cortex.Net.xml @@ -625,6 +625,16 @@ The optional enhancer to use. default enhancer is the deep enhancer. The observable. + + + Creates a computed value. + + The type of the elements. + The shared state to operate on. + The getter function to use. + The name of the observable collection. + The computed value. + Extension methods that deal with Reactions on an ISharedState instance. @@ -2137,6 +2147,13 @@ Event that fires after the value has changed. + + + Registers the secified event handler, and optionally fires it first. + + The event handler to register. + Whether to fire the event handler immediately. + Interface for Computed values. diff --git a/src/Cortex.Net/IComputedValue.cs b/src/Cortex.Net/IComputedValue.cs index 2b8c776..5b07a3b 100644 --- a/src/Cortex.Net/IComputedValue.cs +++ b/src/Cortex.Net/IComputedValue.cs @@ -29,6 +29,13 @@ public interface IComputedValue : IComputedValue, IValue /// Event that fires after the value has changed. /// event EventHandler> Changed; + + /// + /// Registers the secified event handler, and optionally fires it first. + /// + /// The event handler to register. + /// Whether to fire the event handler immediately. + void Observe(EventHandler> changedEventHandler, bool fireImmediately); } /// diff --git a/test/Cortex.Net.Test/Base/ActionTests.cs b/test/Cortex.Net.Test/Base/ActionTests.cs index 9f04bd3..453929b 100644 --- a/test/Cortex.Net.Test/Base/ActionTests.cs +++ b/test/Cortex.Net.Test/Base/ActionTests.cs @@ -51,7 +51,7 @@ public void ActionShouldWrapInTransaction() { var values = new List(); - var observable = new ObservableValue(this.sharedState, "int", this.sharedState.ReferenceEnhancer(), 0); + var observable = this.sharedState.Box(0); this.sharedState.Autorun((r) => values.Add(observable.Value)); @@ -72,7 +72,7 @@ public void ActionShouldWrapInTransaction() [Fact] public void ActionModificationsShouldBePickedUp1() { - var a = new ObservableValue(this.sharedState, "int", this.sharedState.ReferenceEnhancer(), 1); + var a = this.sharedState.Box(1); var i = 3; var b = 0; @@ -104,7 +104,7 @@ public void ActionModificationsShouldBePickedUp1() [Fact] public void ActionModificationsShouldBePickedUp2() { - var a = new ObservableValue(this.sharedState, "int", this.sharedState.ReferenceEnhancer(), 1); + var a = this.sharedState.Box(1); var b = 0; @@ -135,12 +135,11 @@ public void ActionModificationsShouldBePickedUp2() [Fact] public void ActionModificationsShouldBePickedUp3() { - var a = new ObservableValue(this.sharedState, "int", this.sharedState.ReferenceEnhancer(), 1); + var a = this.sharedState.Box(1); var b = 0; - var doubler = new ComputedValue(this.sharedState, new ComputedValueOptions( - () => a.Value * 2, "doubler")); + var doubler = this.sharedState.Computed(() => a.Value * 2, "doubler"); doubler.Observe( (s, e) => @@ -168,8 +167,8 @@ public void ActionModificationsShouldBePickedUp3() [Fact] public void ActionShouldBeUntracked() { - var a = new ObservableValue(this.sharedState, "int", this.sharedState.ReferenceEnhancer(), 3); - var b = new ObservableValue(this.sharedState, "int", this.sharedState.ReferenceEnhancer(), 4); + var a = this.sharedState.Box(3); + var b = this.sharedState.Box(4); var latest = 0; var runs = 0; @@ -222,7 +221,7 @@ public void ActionShouldBeUntracked() [Fact] public void ShouldBePossibleToCreateAutorunInAction() { - var a = new ObservableValue(this.sharedState, "int", this.sharedState.ReferenceEnhancer(), 1); + var a = this.sharedState.Box(1); var values = new List(); var adder = this.CreateAction(increment => @@ -251,19 +250,19 @@ public void ShouldBePossibleToCreateAutorunInAction() [Fact] public void ShouldBePossibleToChangeUnobservedStateInActionCalledFromComputed() { - var a = new ObservableValue(this.sharedState, "int", this.sharedState.ReferenceEnhancer(), 2); + var a = this.sharedState.Box(2); var testAction = this.sharedState.CreateAction(() => { a.Value = 3; }); - var c = new ComputedValue(this.sharedState, new ComputedValueOptions( + var c = this.sharedState.Computed( () => { testAction(); return 0; - }, "computed")); + }, "computed"); this.sharedState.Autorun(r => { @@ -280,15 +279,15 @@ public void ShouldBePossibleToChangeUnobservedStateInActionCalledFromComputed() [Fact] public void ShouldBePossibleToChangeObservedStateInActionCalledFromComputedIfRunInsideAllowStateChange() { - var a = new ObservableValue(this.sharedState, "int", this.sharedState.ReferenceEnhancer(), 2); + var a = this.sharedState.Box(2); var d = this.sharedState.Autorun(r => { int i = a.Value; }); - ComputedValue c = null; - ComputedValue c2 = null; + IComputedValue c = null; + IComputedValue c2 = null; var testAction = this.sharedState.CreateAction(() => { @@ -312,19 +311,19 @@ public void ShouldBePossibleToChangeObservedStateInActionCalledFromComputedIfRun }); }); - c = new ComputedValue(this.sharedState, new ComputedValueOptions( + c = this.sharedState.Computed( () => { testAction(); return a.Value; - }, "computed")); + }, "computed"); - c2 = new ComputedValue(this.sharedState, new ComputedValueOptions( + c2 = this.sharedState.Computed( () => { a.Value = 6; return a.Value; - }, "computed")); + }, "computed"); int j = c.Value; @@ -337,7 +336,7 @@ public void ShouldBePossibleToChangeObservedStateInActionCalledFromComputedIfRun [Fact] public void ShouldNotBePossibleToChangeObservedStateInAnActionCalledFromComputed() { - var a = new ObservableValue(this.sharedState, "int", this.sharedState.ReferenceEnhancer(), 2); + var a = this.sharedState.Box(2); var d = this.sharedState.Autorun(r => { @@ -349,12 +348,12 @@ public void ShouldNotBePossibleToChangeObservedStateInAnActionCalledFromComputed a.Value = 3; }); - var c = new ComputedValue(this.sharedState, new ComputedValueOptions( + var c = this.sharedState.Computed( () => { testAction(); return a.Value; - }, "computed")); + }, "computed"); Assert.Throws(() => { @@ -370,8 +369,8 @@ public void ShouldNotBePossibleToChangeObservedStateInAnActionCalledFromComputed [Fact] public void ActionInAutorunShouldBeUntracked() { - var a = new ObservableValue(this.sharedState, "a", this.sharedState.ReferenceEnhancer(), 2); - var b = new ObservableValue(this.sharedState, "b", this.sharedState.ReferenceEnhancer(), 3); + var a = this.sharedState.Box(2); + var b = this.sharedState.Box(3); var values = new List(); @@ -400,7 +399,7 @@ public void ActionInAutorunShouldBeUntracked() public void ExceptionsInActionsShouldNotAffectGlobalState() { int autoRunTimes = 0; - var count = new ObservableValue(this.sharedState, "a", this.sharedState.ReferenceEnhancer(), 2); + var count = this.sharedState.Box(2); var add = this.sharedState.CreateAction(() => { @@ -450,7 +449,7 @@ public void RunInAction() } }; - var observable = new ObservableValue(this.sharedState, "a", this.sharedState.ReferenceEnhancer(), 0); + var observable = this.sharedState.Box(0); var d = this.sharedState.Autorun(r => { @@ -501,11 +500,11 @@ public void RunInAction() public void ActionInAutoRunDoesNotKeepComputedValuesAlive() { var calls = 0; - var computed = new ComputedValue(this.sharedState, new ComputedValueOptions( + var computed = this.sharedState.Computed( () => { return calls++; - }, "computed")); + }, "computed"); Action callComputedTwice = () => { @@ -546,13 +545,13 @@ public void ComputedValuesAndActions() { var calls = 0; - var number = new ObservableValue(this.sharedState, "a", this.sharedState.ReferenceEnhancer(), 1); - var squared = new ComputedValue(this.sharedState, new ComputedValueOptions( + var number = this.sharedState.Box(1); + var squared = this.sharedState.Computed( () => { calls++; return number.Value * number.Value; - }, "squared")); + }, "squared"); var changeNumber10Times = this.sharedState.CreateAction(() => {