public void TestActionModificationPickup1() { var a = ObservableValue <int> .From(1); var i = 3; var b = 0; Reactions.Autorun(r => { b = a.Value * 2; }); Assert.Equal(2, b); var action = Actions.CreateAction("action", () => { a.Value = ++i; }); action(); Assert.Equal(8, b); action(); Assert.Equal(10, b); }
public void TestActionModificationPickup2() { var a = ObservableValue <int> .From(1); var b = 0; Reactions.Autorun(r => { b = a.Value * 2; }); Assert.Equal(2, b); var action = Actions.CreateAction("action", () => { a.Value = a.Value + 1; // ha, no loop! }); action(); Assert.Equal(4, b); action(); Assert.Equal(6, b); }
public void TestList() { var StringList = Types.List(Types.String); var values = StringList.Create(new string[] { "one", "two" }, new TestEnv()); Assert.NotNull(values); Assert.Equal(2, values.Length); Assert.Equal("one", values[0]); Assert.Equal("two", values[1]); var autos = new List <string>(); Reactions.Autorun((r) => { autos.AddRange(values.ToList()); }); var patches = new List <IJsonPatch>(); values.OnPatch((patch, _patch) => { patches.Add(patch); }); values.Unprotected(); values.Add("three"); Assert.Equal(5, autos.Count); Assert.Single(patches); }
public void TestAutorunInAction() { var a = ObservableValue <int> .From(1); var values = new List <int>(); var adder = Actions.CreateAction <int, IDisposable>("incr", (incr) => { return(Reactions.Autorun(() => { values.Add(a.Value + incr); })); }); var d1 = adder(2); a.Value = 3; var d2 = adder(17); a.Value = 24; d1.Dispose(); a.Value = 11; d2.Dispose(); a.Value = 100; // n.b. order could swap as autorun creation order doesn't guarantee stuff Assert.Equal(new int[] { 3, 5, 20, 26, 41, 28 }, values.ToArray()); }
public void TestWrapInTransaction() { var values = new List <int>(); var observable = ObservableValue <int> .From(0); Reactions.Autorun(r => { values.Add(observable.Value); }); var increment = Actions.CreateAction <int, int>("Increment", (amount) => { observable.Value += amount * 2; observable.Value -= amount; // oops return(observable.Value); }); var value = increment(7); Assert.Equal(7, value); Assert.Equal(2, values.Count); Assert.Equal(0, values[0]); Assert.Equal(7, values[1]); }
public void TestObservableAutoRun() { var box = ObservableValue <int> .From(1); var reader = box as IValueReader <int>; var writer = box as IValueWriter <int>; var values = new List <int>(); Reactions.Autorun((reaction) => { Assert.NotNull(reaction); if (reader.Value == -1) { reaction.Dispose(); } values.Add(reader.Value); }); writer.Value = 2; writer.Value = 2; writer.Value = -1; writer.Value = 3; writer.Value = 4; Assert.Equal(3, values.Count); Assert.Equal(1, values[0]); Assert.Equal(2, values[1]); Assert.Equal(-1, values[2]); }
public void TestRunInAction() { var observable = ObservableValue <int> .From(0); var values = new List <int>(); var d = Reactions.Autorun(() => values.Add(observable.Value)); var res = Actions.RunInAction <int>("increment", () => { observable.Value = observable.Value + 6 * 2; observable.Value = observable.Value - 3; // oops return(2); }); Assert.Equal(2, res); Assert.Equal(new[] { 0, 9 }, values.ToArray()); res = Actions.RunInAction <int>("another", () => { observable.Value = observable.Value + 5 * 2; observable.Value = observable.Value - 4; // oops return(3); }); Assert.Equal(3, res); Assert.Equal(new[] { 0, 9, 15 }, values.ToArray()); d.Dispose(); }
public void TestActionAutorunUnTracked() { var a = ObservableValue <int> .From(2); var b = ObservableValue <int> .From(3); var values = new List <int>(); var multiplier = Actions.CreateAction <int, int>("multiplier", (val) => val * b.Value); var d = Reactions.Autorun(() => { values.Add(multiplier(a.Value)); }); a.Value = 3; b.Value = 4; a.Value = 5; d.Dispose(); a.Value = 6; Assert.Equal(new[] { 6, 9, 20 }, values.ToArray()); }
public void TestAllowModificationInComputed() { var a = ObservableValue <int> .From(2); var d = Reactions.Autorun(() => { var x = a.Value; }); IComputedValue <int> c2 = null; var action = Actions.CreateAction("action", () => { Actions.AllowStateChangesInsideComputed(() => { a.Value = 3; //// a second level computed should throw Assert.Throws <CaughtException>(() => { // /Computed values are not allowed to cause side effects by changing observables that are already being observed/ var x = c2.Value; }); }); Assert.Equal(3, a.Value); Assert.Throws <Exception>(() => { // /Computed values are not allowed to cause side effects by changing observables that are already being observed/ a.Value = 4; }); }); var c = ComputedValue <int> .From(() => { action(); return(a.Value); }); c2 = ComputedValue <int> .From(() => { a.Value = 6; return(a.Value); }); var _ = c.Value; d.Dispose(); }
public void TestActionUnTracked() { var a = ObservableValue <int> .From(3); var b = ObservableValue <int> .From(4); var latest = 0; var runs = 0; var action = Actions.CreateAction <int>("action", (baseValue) => { b.Value = baseValue * 2; latest = b.Value; // without action this would trigger loop }); var d = Reactions.Autorun(r => { runs++; var current = a.Value; action(current); }); Assert.Equal(6, b.Value); Assert.Equal(6, latest); a.Value = 7; Assert.Equal(14, b.Value); Assert.Equal(14, latest); a.Value = 8; Assert.Equal(16, b.Value); Assert.Equal(16, latest); b.Value = 7; // should have no effect Assert.Equal(8, a.Value); Assert.Equal(7, b.Value); Assert.Equal(16, latest); // effect not triggered a.Value = 3; Assert.Equal(6, b.Value); Assert.Equal(6, latest); Assert.Equal(4, runs); d.Dispose(); }
public void TestAutorun2() { var list = ObservableList <int> .From(new[] { 4, 2, 3 }); List <int> sorted = null; var sortedX = ComputedValue <List <int> > .From(() => { var splice = list.ToList(); splice.Sort(); return(splice); }); Reactions.Autorun((r) => { sorted = sortedX.Value; }); Assert.Equal(4, list[0]); Assert.Equal(2, list[1]); Assert.Equal(3, list[2]); Assert.Equal(2, sorted[0]); Assert.Equal(3, sorted[1]); Assert.Equal(4, sorted[2]); list.Add(1); Assert.Equal(4, list[0]); Assert.Equal(2, list[1]); Assert.Equal(3, list[2]); Assert.Equal(1, list[3]); Assert.Equal(1, sorted[0]); Assert.Equal(2, sorted[1]); Assert.Equal(3, sorted[2]); Assert.Equal(4, sorted[3]); list.Shift(); Assert.Equal(2, list[0]); Assert.Equal(3, list[1]); Assert.Equal(1, list[2]); Assert.Equal(1, sorted[0]); Assert.Equal(2, sorted[1]); Assert.Equal(3, sorted[2]); }
public void TestAutorun1() { var list = ObservableList <int> .From(); var count = 0; Reactions.Autorun((r) => { var x = list.ToString(); count++; }); list.Push(1); Assert.Equal(2, count); }
public void TestCounter() { var counter = new Counter(); var counts = new List <int>(); Reactions.Autorun(() => { counts.Add(counter.Count); }); counter.Increment(); counter.Increment(); Assert.Equal(3, counts.Count); Assert.Equal(0, counts[0]); Assert.Equal(1, counts[1]); Assert.Equal(2, counts[2]); }
public void TestAutorunInActionDoesNotKeepComputedAlive() { var calls = 0; var computed = ComputedValue <int> .From(() => calls ++); Action callComputedTwice = () => { var x = computed.Value; var y = computed.Value; }; Action <Action> runWithMemoizing = (fun) => { Reactions.Autorun(fun).Dispose(); }; callComputedTwice(); Assert.Equal(2, calls); runWithMemoizing(callComputedTwice); Assert.Equal(3, calls); callComputedTwice(); Assert.Equal(5, calls); runWithMemoizing(() => { Actions.RunInAction <int>("x", () => { callComputedTwice(); return(0); }); }); Assert.Equal(6, calls); callComputedTwice(); Assert.Equal(8, calls); }
public void TestComputedAutorun() { var box = ObservableValue <int> .From(3); var reader = box as IValueReader <int>; var writer = box as IValueWriter <int>; var x = ComputedValue <int> .From(() => reader.Value * 2); var values = new List <int>(); Reactions.Autorun((reaction) => { values.Add(x.Value); }); writer.Value = 5; writer.Value = 10; Assert.Equal(3, values.Count); Assert.Equal(6, values[0]); Assert.Equal(10, values[1]); Assert.Equal(20, values[2]); }
public void TestModificationInComputed() { var a = ObservableValue <int> .From(2); var action = Actions.CreateAction("action", () => { a.Value = 3; }); var c = ComputedValue <object> .From(() => { action(); return(null); }); var d = Reactions.Autorun(() => { // expect not to throws var x = c.Value; }); d.Dispose(); }
public void TestComputedValuesAndAction() { var calls = 0; var number = ObservableValue <int> .From(1); var squared = ComputedValue <int> .From(() => { calls++; return(number.Value *number.Value); }); var changeNumber10Times = Actions.CreateAction("changeNumber10Times", () => { var x = squared.Value; var y = squared.Value; for (int i = 0; i < 10; i++) { number.Value = number.Value + 1; } }); changeNumber10Times(); Assert.Equal(1, calls); Reactions.Autorun(r => { changeNumber10Times(); Assert.Equal(2, calls); }); Assert.Equal(2, calls); changeNumber10Times(); Assert.Equal(3, calls); }
public void TestModificationErrorInComputed() { var a = ObservableValue <int> .From(2); var d = Reactions.Autorun(() => { var x = a.Value; }); var action = Actions.CreateAction("action", () => { a.Value = 3; }); var c = ComputedValue <int> .From(() => { action(); return(a.Value); }); Assert.Throws <Exception>(() => { var x = c.Value; }); d.Dispose(); }
public void TestObserveValue() { var map = ObservableMap <object, object> .From(); var hasX = false; object valueX = null; object valueY = null; Reactions.Autorun((r) => { hasX = map.Has("x"); }); Reactions.Autorun((r) => { valueX = map["x"]; }); Reactions.Autorun((r) => { valueY = map["y"]; }); Assert.False(hasX); Assert.Null(valueX); map["x"] = 3; Assert.True(hasX); Assert.Equal(3, valueX); map["x"] = 4; Assert.True(hasX); Assert.Equal(4, valueX); map.Remove("x"); Assert.False(hasX); Assert.Null(valueX); map["x"] = 5; Assert.True(hasX); Assert.Equal(5, valueX); Assert.Null(valueY); map.Merge(new Map <object, object> { { "y", "hi" } }); Assert.Equal("hi", valueY); map.Merge(new Map <object, object> { { "y", "hello" } }); Assert.Equal("hello", valueY); map.Replace(new Map <object, object> { { "y", "stuff" }, { "z", "zoef" } }); Assert.Equal("stuff", valueY); var keys = map.Keys.ToList(); Assert.Equal(2, keys.Count); Assert.Equal("y", keys[0]); Assert.Equal("z", keys[1]); }
public void TestObserver() { var map = ObservableMap <object, object> .From(); IList <object> keys = null; IList <object> values = null; IList <KeyValuePair <object, object> > entries = null; Reactions.Autorun((r) => { keys = map.Keys.ToList(); }); Reactions.Autorun((r) => { values = map.Values.ToList(); }); Reactions.Autorun((r) => { entries = map.ToList(); }); map["a"] = 1; Assert.Single(keys); Assert.Equal("a", keys[0]); Assert.Single(values); Assert.Equal(1, values[0]); Assert.Single(entries); Assert.Equal("a", entries[0].Key); Assert.Equal(1, entries[0].Value); // should not retrigger: keys = null; values = null; entries = null; map["a"] = 1; Assert.Null(keys); Assert.Null(values); Assert.Null(entries); map["a"] = 2; Assert.Single(values); Assert.Equal(2, values[0]); Assert.Single(entries); Assert.Equal("a", entries[0].Key); Assert.Equal(2, entries[0].Value); map["b"] = 3; Assert.Equal(2, keys.Count); Assert.Equal("a", keys[0]); Assert.Equal("b", keys[1]); Assert.Equal(2, values.Count); Assert.Equal(2, values[0]); Assert.Equal(3, values[1]); Assert.Equal(2, entries.Count); Assert.Equal("a", entries[0].Key); Assert.Equal(2, entries[0].Value); Assert.Equal("b", entries[1].Key); Assert.Equal(3, entries[1].Value); map.Has("c"); Assert.Equal(2, keys.Count); Assert.Equal("a", keys[0]); Assert.Equal("b", keys[1]); Assert.Equal(2, values.Count); Assert.Equal(2, values[0]); Assert.Equal(3, values[1]); Assert.Equal(2, entries.Count); Assert.Equal("a", entries[0].Key); Assert.Equal(2, entries[0].Value); Assert.Equal("b", entries[1].Key); Assert.Equal(3, entries[1].Value); map.Remove("a"); Assert.Single(keys); Assert.Equal("b", keys[0]); Assert.Single(values); Assert.Equal(3, values[0]); Assert.Single(entries); Assert.Equal("b", entries[0].Key); Assert.Equal(3, entries[0].Value); }