public async Task TwoWay_Cleans_JavascriptObject_Listeners_When_Object_Is_Not_Part_Of_The_Graph_Array_Js_Context() { var dataContext = new BasicListTestViewModel(); var child = new BasicTestViewModel(); dataContext.Children.Add(child); var test = new TestInContextAsync() { Bind = (win) => Bind(win, dataContext, JavascriptBindingMode.TwoWay), Test = async(mb) => { var js = mb.JsRootObject; CheckObjectObservability(js, ObjectObservability.ReadOnlyObservable); var childrenJs = GetCollectionAttribute(js, "Children"); var childJs = childrenJs.GetValue(0); await CheckObjectObservabilityAsync(childJs, ObjectObservability.Observable); var observableCollection = GetAttribute(js, "Children"); Call(observableCollection, "pop"); await CheckHasListenerAsync(childJs, false); } }; await RunAsync(test); }
public async Task TwoWay_Unlistens_When_Property_Is_Changed(BasicTestViewModel remplacementChild) { var child = new BasicTestViewModel(); var dataContext = new BasicTestViewModel { Child = child }; var test = new TestInContextAsync() { Bind = (win) => HtmlBinding.Bind(win, dataContext, JavascriptBindingMode.TwoWay), Test = async(mb) => { var js = mb.JsRootObject; child.ListenerCount.Should().Be(1); await DoSafeAsyncUI(() => dataContext.Child = remplacementChild); await WaitAnotherWebContextCycle(); child.ListenerCount.Should().Be(0); //If still listening to child, this will raise an exception //for changing property on the wrong thread var third = new BasicTestViewModel(); Action safe = () => child.Child = third; await DoSafeAsync(() => safe.Should().NotThrow()); } }; await RunAsync(test); }
public async Task TwoWay_should_clean_javascriptObject_listeners_when_object_is_not_part_of_the_graph_array_js_context() { var datacontext = new BasicListTestViewModel(); var child = new BasicTestViewModel(); datacontext.Children.Add(child); var test = new TestInContextAsync() { Bind = (win) => Bind(win, datacontext, JavascriptBindingMode.TwoWay), Test = async(mb) => { var js = mb.JsRootObject; CheckReadOnly(js, true); var childrenJs = GetCollectionAttribute(js, "Children"); var childJs = childrenJs.GetValue(0); CheckReadOnly(childJs, false); var operabelCollection = GetAttribute(js, "Children"); Call(operabelCollection, "pop"); await Task.Delay(150); CheckHasListener(childJs, false); } }; await RunAsync(test); }
public async Task TwoWay_Cleans_JavascriptObject_Listeners_When_Object_Is_Not_Part_Of_The_Graph_Multiple_Changes(BasicTestViewModel remplacementChild) { var dataContext = new BasicFatherTestViewModel(); var child = new BasicTestViewModel(); dataContext.Child = child; var tempChild1 = new BasicTestViewModel(); var tempChild2 = new BasicTestViewModel(); var test = new TestInContextAsync() { Bind = (win) => Bind(win, dataContext, JavascriptBindingMode.TwoWay), Test = async(mb) => { var js = mb.JsRootObject; var childJs = GetAttribute(js, "Child"); CheckObjectObservability(childJs, ObjectObservability.Observable); await DoSafeAsyncUI(() => { dataContext.Child = tempChild1; dataContext.Child = tempChild2; dataContext.Child = remplacementChild; }); await CheckHasListenerAsync(childJs, false); } }; await RunAsync(test); }
public async Task TwoWay_should_clean_javascriptObject_listeners_when_object_is_not_part_of_the_graph(BasicTestViewModel remplacementChild) { var datacontext = new BasicFatherTestViewModel(); var child = new BasicTestViewModel(); datacontext.Child = child; var test = new TestInContextAsync() { Bind = (win) => Bind(win, datacontext, JavascriptBindingMode.TwoWay), Test = async(mb) => { var js = mb.JsRootObject; var childJs = GetAttribute(js, "Child"); CheckReadOnly(childJs, false); DoSafeUI(() => datacontext.Child = remplacementChild); await Task.Delay(150); CheckHasListener(childJs, false); } }; await RunAsync(test); }
public async Task TwoWay_should_clean_javascriptObject_listeners_when_object_is_not_part_of_the_graph_js() { var datacontext = new BasicFatherTestViewModel(); var child = new BasicTestViewModel(); datacontext.Child = child; var test = new TestInContextAsync() { Bind = (win) => Bind(win, datacontext, JavascriptBindingMode.TwoWay), Test = async(mb) => { var js = mb.JsRootObject; var childJs = GetAttribute(js, "Child"); CheckReadOnly(childJs, false); var nullJs = Factory.CreateNull(); SetAttribute(js, "Child", nullJs); await Task.Delay(150); DoSafeUI(() => datacontext.Child.Should().BeNull()); child.ListenerCount.Should().Be(0); await Task.Delay(100); CheckHasListener(childJs, false); } }; await RunAsync(test); }
public async Task TwoWay_Listens_after_set_from_javascript_side() { var root = new BasicTestTwoChildrenViewModel(); var child = new BasicTestViewModel(); root.Child1 = child; var test = new TestInContextAsync() { Bind = (win) => Bind(win, root, JavascriptBindingMode.TwoWay), Test = async(mb) => { var rootJs = mb.JsRootObject; var childJs = GetAttribute(rootJs, "Child1"); await SetAttributeAsync(rootJs, "Child2", childJs); await DoSafeAsyncUI(() => { root.Child2.Should().Be(child); root.Child1 = null; }); child.ListenerCount.Should().Be(1); } }; await RunAsync(test); }
public async Task TwoWay_Unlistens_When_Object_Is_Not_Part_Of_The_Graph_Respecting_Cycle( BasicTestViewModel root, BasicTestViewModel breaker, BasicTestViewModel[] survivores, BasicTestViewModel[] cleaned) { var test = new TestInContextAsync() { Bind = (win) => Bind(win, root, JavascriptBindingMode.TwoWay), Test = async(mb) => { await DoSafeAsyncUI(() => breaker.Child = null); //This block allow to wait for another loop of UI/Js context thread to be executed { var child = await EvaluateSafeUIAsync(() => breaker.Child); child.Should().BeNull(); } survivores.ForEach(sur => sur.ListenerCount.Should().Be(1)); cleaned.ForEach(sur => sur.ListenerCount.Should().Be(0)); } }; await RunAsync(test); }
public async Task TwoWay_Unlistens_When_Object_Is_Not_Part_of_The_Graph_Respecting_Cycle_Transient_Changes( BasicTestViewModel root, BasicTestViewModel breaker, BasicTestViewModel[] survivors, BasicTestViewModel[] cleaned) { var tempChild1 = new BasicTestViewModel(); var tempChild2 = new BasicTestViewModel(); var test = new TestInContextAsync() { Bind = (win) => Bind(win, root, JavascriptBindingMode.TwoWay), Test = async(mb) => { await DoSafeAsyncUI(() => { breaker.Child = tempChild1; breaker.Child = tempChild2; breaker.Child = null; }); survivors.ForEach(sur => sur.ListenerCount.Should().Be(1)); cleaned.ForEach(sur => sur.ListenerCount.Should().Be(0)); new[] { tempChild1, tempChild2 }.ForEach(sur => sur.ListenerCount.Should().Be(0)); } }; await RunAsync(test); }
public async Task TwoWay_Unlistens_When_Property_Has_Transients_Changes(BasicTestViewModel remplacementChild) { var child = new BasicTestViewModel(); var dataContext = new BasicTestViewModel { Child = child }; var tempChild1 = new BasicTestViewModel(); var tempChild2 = new BasicTestViewModel(); var test = new TestInContextAsync() { Bind = (win) => HtmlBinding.Bind(win, dataContext, JavascriptBindingMode.TwoWay), Test = async(mb) => { var js = mb.JsRootObject; child.ListenerCount.Should().Be(1); await DoSafeAsyncUI(() => { dataContext.Child = tempChild1; dataContext.Child = tempChild2; dataContext.Child = remplacementChild; }); await WaitAnotherWebContextCycle(); tempChild1.ListenerCount.Should().Be(0); tempChild2.ListenerCount.Should().Be(0); child.ListenerCount.Should().Be(0); } }; await RunAsync(test); }
public async Task TwoWay_Cleans_Javascript_Objects_Cache_When_Object_Is_Not_Part_Of_The_Graph( BasicTestViewModel replacementChild) { var dataContext = new BasicFatherTestViewModel(); var child = new BasicTestViewModel(); dataContext.Child = child; var test = new TestInContextAsync() { Bind = (win) => HtmlBinding.Bind(win, dataContext, JavascriptBindingMode.TwoWay), Test = async(mb) => { var js = mb.JsRootObject; var childJs = GetAttribute(js, "Child"); await DoSafeAsyncUI(() => dataContext.Child = replacementChild); await WaitAnotherWebContextCycle(); var myCommand = await GetAttributeAsync(js, "Command"); await DoSafeAsync(() => Call(myCommand, "Execute", childJs)); await DoSafeAsyncUI(() => { dataContext.CallCount.Should().Be(0); dataContext.LastCallElement.Should().BeNull(); }); } }; await RunAsync(test); }
public async Task TwoWay_Calls_Command_With_Correct_Argument() { var fakeTestViewModel = new BasicFatherTestViewModel(); var child = new BasicTestViewModel(); fakeTestViewModel.Child = child; var test = new TestInContextAsync() { Bind = (win) => HtmlBinding.Bind(win, fakeTestViewModel, JavascriptBindingMode.TwoWay), Test = async(mb) => { var js = mb.JsRootObject; var childJs = GetAttribute(js, "Child"); var jsCommand = GetAttribute(js, "Command"); await DoSafeAsync(() => Call(jsCommand, "Execute", childJs)); await DoSafeAsyncUI(() => { fakeTestViewModel.CallCount.Should().Be(1); fakeTestViewModel.LastCallElement.Should().Be(child); }); } }; await RunAsync(test); }
public async Task TwoWay_Cleans_JavascriptObject_Listeners_When_Object_Is_Not_Part_Of_The_Graph_Js() { var dataContext = new BasicFatherTestViewModel(); var child = new BasicTestViewModel(); dataContext.Child = child; var test = new TestInContextAsync() { Bind = (win) => Bind(win, dataContext, JavascriptBindingMode.TwoWay), Test = async(mb) => { var js = mb.JsRootObject; var childJs = GetAttribute(js, "Child"); CheckObjectObservability(childJs, ObjectObservability.Observable); var nullJs = Factory.CreateNull(); await SetAttributeAsync(js, "Child", nullJs); await DoSafeAsyncUI(() => dataContext.Child.Should().BeNull()); child.ListenerCount.Should().Be(0); //await WaitAnotherWebContextCycle(); await CheckHasListenerAsync(childJs, false); } }; await RunAsync(test); }
public async Task TwoWay_cleans_javascriptObject_listeners_when_object_is_not_part_of_the_graph_array_context(BasicTestViewModel remplacementChild) { var datacontext = new BasicListTestViewModel(); var child = new BasicTestViewModel(); datacontext.Children.Add(child); var test = new TestInContextAsync() { Bind = (win) => Bind(win, datacontext, JavascriptBindingMode.TwoWay), Test = async(mb) => { var js = mb.JsRootObject; CheckObjectObservability(js, ObjectObservability.ReadOnlyObservable); var childrenJs = GetCollectionAttribute(js, "Children"); var childJs = childrenJs.GetValue(0); CheckObjectObservability(childJs, ObjectObservability.Observable); DoSafeUI(() => datacontext.Children[0] = remplacementChild); await Task.Delay(150); CheckHasListener(childJs, false); } }; await RunAsync(test); }
private static BasicTestViewModel BuildLongCircular() { var circularLong = new BasicTestViewModel { Child = new BasicTestViewModel { Child = new BasicTestViewModel() } }; circularLong.Child.Child.Child = circularLong; return(circularLong); }
public async Task TwoWay_ResultCommand_Can_Be_Listened_From_CSharp_When_Used_As_Vm() { var child = new BasicTestViewModel(); var function = Substitute.For <Func <int, BasicTestViewModel> >(); function.Invoke(Arg.Any <int>()).Returns(child); var dataContext = new FactoryFatherTestViewModel(function); var test = new TestInContextAsync() { Path = TestContext.IndexPromise, Bind = (win) => HtmlBinding.Bind(win, dataContext, JavascriptBindingMode.TwoWay), Test = async(mb) => { var js = mb.JsRootObject; var factory = GetAttribute(js, "Factory"); var jsCommand = GetAttribute(factory, "CreateObject"); var cb = GetCallBackObject(); Call(jsCommand, "Execute", _WebView.Factory.CreateInt(25), cb); await Task.Delay(200); DoSafeUI(() => { }); var resValue = _WebView.GetGlobal().GetValue("res"); var originalValue = GetAttribute(resValue, nameof(BasicTestViewModel.Value)).GetIntValue(); originalValue.Should().Be(-1); SetAttribute(js, nameof(FactoryFatherTestViewModel.Child), resValue); var res = GetAttribute(js, nameof(FactoryFatherTestViewModel.Child)); res.IsObject.Should().BeTrue(); await Task.Delay(200); DoSafeUI(() => dataContext.Child.Should().Be(child)); var newInt = 45; SetAttribute(resValue, nameof(BasicTestViewModel.Value), _WebView.Factory.CreateInt(newInt)); var updatedValue = GetAttribute(resValue, nameof(BasicTestViewModel.Value)).GetIntValue(); updatedValue.Should().Be(newInt); await Task.Delay(200); DoSafeUI(() => dataContext.Child.Value.Should().Be(newInt)); } }; await RunAsync(test); }
public async Task TwoWay_Listens_To_All_Changes() { var child = new BasicTestViewModel(); var datacontext = new BasicTestViewModel { Child = child }; var test = new TestInContextAsync() { Bind = (win) => HtmlBinding.Bind(win, datacontext, JavascriptBindingMode.TwoWay), Test = async(mb) => { var js = mb.JsRootObject; DoSafeUI(() => datacontext.Child = null); await Task.Delay(300); var third = new BasicTestViewModel(); child.Child = third; DoSafeUI(() => datacontext.Child = child); await Task.Delay(300); DoSafeUI(() => third.Value = 3); await Task.Delay(300); var child1 = GetAttribute(js, "Child"); var child2 = GetAttribute(child1, "Child"); var value = GetIntAttribute(child2, "Value"); value.Should().Be(3); var newvalue = 44; var intJS = _WebView.Factory.CreateInt(newvalue); SetAttribute(child2, "Value", intJS); await Task.Delay(300); DoSafeUI(() => { third.Value.Should().Be(newvalue); }); } }; await RunAsync(test); }
public async Task TwoWay_Unlistens_To_Elements_Removed_From_List_By_Set() { var root = BuildList(); var list = root.Children.ToList(); var removed = list[0]; var test = new TestInContextAsync() { Bind = (win) => Bind(win, root, JavascriptBindingMode.TwoWay), Test = async(mb) => { var newChild = new BasicTestViewModel(); await DoSafeAsyncUI(() => root.Children[0] = newChild); removed.ListenerCount.Should().Be(0); list.Skip(1).ForEach(child => child.ListenerCount.Should().Be(1)); newChild.ListenerCount.Should().Be(1); } }; await RunAsync(test); }
public async Task TwoWay_Unlistens_When_Object_Is_Not_Part_Of_The_Graph_Respecting_Cycle(BasicTestViewModel root, BasicTestViewModel breaker, BasicTestViewModel[] survivores, BasicTestViewModel[] cleaned) { var test = new TestInContextAsync() { Bind = (win) => Bind(win, root, JavascriptBindingMode.TwoWay), Test = async(mb) => { await DoSafeAsyncUI(() => breaker.Child = null); survivores.ForEach(sur => sur.ListenerCount.Should().Be(1)); cleaned.ForEach(sur => sur.ListenerCount.Should().Be(0)); } }; await RunAsync(test); }