public async Task TwoWay_Calls_Command_With_Null_Parameter() { var command = Substitute.For <ICommand>(); var test = new FakeTestViewModel() { Command = command }; var testR = new TestInContextAsync() { Bind = (win) => HtmlBinding.Bind(win, test, JavascriptBindingMode.TwoWay), Test = async(mb) => { var js = mb.JsRootObject; var jsCommand = GetAttribute(js, "Command"); Call(jsCommand, "Execute", _WebView.Factory.CreateNull()); await Task.Delay(150); command.Received().Execute(null); } }; await RunAsync(testR); }
private Task Test_HTMLBinding_Stress_Collection_CreateBinding(JavascriptBindingMode imode, TestPerformanceKind context, TestContext ipath = TestContext.Index) { var r = 100; var datacontext = new TwoList(); datacontext.L1.AddRange(Enumerable.Range(0, r).Select(i => new Skill())); var stopWatch = new Stopwatch(); stopWatch.Start(); var test = new TestInContext() { Path = ipath, Bind = (win) => HtmlBinding.Bind(win, datacontext, imode), Test = (mb) => { stopWatch.Stop(); var ts = stopWatch.ElapsedMilliseconds; _Logger.Info($"Perf: {((double)(ts)) / 1000} sec for {r} iterations"); var js = mb.JsRootObject; var col = GetSafe(() => GetCollectionAttribute(js, "L1")); col.GetArrayLength().Should().Be(r); CheckVsExpectation(ts, context); } }; return(RunAsync(test)); }
public async Task TwoWay_Command_Generic_String_CanExecute_Refresh_Ok() { var command = Substitute.For <ICommand <string> >(); command.CanExecute(Arg.Any <string>()).Returns(true); var datacontexttest = new FakeTestViewModel() { CommandGeneric = command }; var test = new TestInContextAsync() { Path = TestContext.GenericBind, Bind = (win) => HtmlBinding.Bind(win, datacontexttest, JavascriptBindingMode.TwoWay), Test = async(mb) => { var js = mb.JsRootObject; var mycommand = GetAttribute(js, "CommandGeneric"); var res = GetBoolAttribute(mycommand, "CanExecuteValue"); res.Should().BeTrue(); command.CanExecute(Arg.Any <string>()).Returns(false); command.CanExecuteChanged += Raise.EventWith(_ICommand, new EventArgs()); await Task.Delay(100); mycommand = GetAttribute(js, "CommandGeneric"); res = GetBoolAttribute(mycommand, "CanExecuteValue"); res.Should().BeFalse(); } }; 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_Listens_To_Nested_Changes_After_Property_Updates_CSharp_Updates() { _DataContext.MainSkill.Should().BeNull(); var test = new TestInContextAsync() { Bind = (win) => HtmlBinding.Bind(win, _DataContext, JavascriptBindingMode.TwoWay), Test = async(mb) => { var local = new Local { City = "JJC" }; await DoSafeAsyncUI(() => { _DataContext.Local = local; }); await DoSafeAsyncUI(() => { local.City = "Floripa"; }); await WaitAnotherWebContextCycle(); var js = mb.JsRootObject; var jsLocal = await GetAttributeAsync(js, "Local"); var city = GetStringAttribute(jsLocal, "City"); city.Should().Be("Floripa"); } }; await RunAsync(test); }
public async Task TwoWay_Maps_None_Generic_List() { var dataContext = new VmWithList(); dataContext.List.Add(888); var test = new TestInContextAsync() { Bind = (win) => HtmlBinding.Bind(win, dataContext, JavascriptBindingMode.TwoWay), Test = async(mb) => { var js = mb.JsRootObject; var col = await GetCollectionAttributeAsync(js, "List"); col.GetArrayLength().Should().Be(1); var res = GetAttribute(js, "List"); await CallAsync(res, "push", _WebView.Factory.CreateString("newvalue")); col = await GetCollectionAttributeAsync(js, "List"); col.GetArrayLength().Should().Be(2); await DoSafeAsyncUI(() => { dataContext.List.Should().HaveCount(2); dataContext.List[1].Should().Be("newvalue"); }); } }; 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_CommandWithoutParameter_Updates_From_Null() { var command = Substitute.For <ICommandWithoutParameter>(); var fakeTestViewModel = new FakeTestViewModel(); var test = new TestInContextAsync() { Bind = (win) => HtmlBinding.Bind(win, fakeTestViewModel, JavascriptBindingMode.TwoWay), Test = async(mb) => { var js = mb.JsRootObject; var jsCommand = GetAttribute(js, "Command"); jsCommand.IsNull.Should().BeTrue(); await DoSafeAsyncUI(() => fakeTestViewModel.CommandWithoutParameters = command); await WaitAnotherWebContextCycle(); jsCommand = await GetAttributeAsync(js, "CommandWithoutParameters"); await DoSafeAsync(() => Call(jsCommand, "Execute")); await DoSafeAsyncUI(() => command.Received().Execute()); } }; await RunAsync(test); }
public async Task TwoWay_Maps_CommandGeneric() { var command = Substitute.For <ICommand <string> >(); var fakeTestViewModel = new FakeTestViewModel() { CommandGeneric = command }; var test = new TestInContext() { Bind = (win) => HtmlBinding.Bind(win, fakeTestViewModel, JavascriptBindingMode.TwoWay), Test = (mb) => { var js = ((HtmlBinding)mb).JsBrideRootObject as JsGenericObject; var jsCommand = js.GetAttribute("CommandGeneric") as JsCommand <string>; jsCommand.Should().NotBeNull(); jsCommand.ToString().Should().Be("{}"); jsCommand.Type.Should().Be(JsCsGlueType.Command); jsCommand.CachableJsValue.Should().NotBeNull(); } }; await RunAsync(test); }
public async Task TwoWay_Updates_Command_From_Null() { var completion = new TaskCompletionSource <object>(); var command = Substitute.For <ICommand>(); command.CanExecute(Arg.Any <object>()).Returns(true); command.When(cmd => cmd.Execute(Arg.Any <object>())).Do(x => completion.SetResult(x[0])); var fakeTestViewModel = new FakeTestViewModel(); var test = new TestInContextAsync() { Bind = (win) => HtmlBinding.Bind(win, fakeTestViewModel, JavascriptBindingMode.TwoWay), Test = async(mb) => { var js = mb.JsRootObject; var jsCommand = GetAttribute(js, "Command"); jsCommand.IsNull.Should().BeTrue(); await DoSafeAsyncUI(() => fakeTestViewModel.Command = command); await WaitAnotherWebContextCycle(); jsCommand = await GetAttributeAsync(js, "Command"); await DoSafeAsync(() => Call(jsCommand, "Execute", js)); var calledValue = await completion.Task; calledValue.Should().Be(fakeTestViewModel); } }; 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_Maps_SimpleCommand_With_Correct_Name() { var command = Substitute.For <ISimpleCommand>(); var simpleCommandTestViewModel = new SimpleCommandTestViewModel() { SimpleCommandNoArgument = command }; var test = new TestInContext() { Bind = (win) => HtmlBinding.Bind(win, simpleCommandTestViewModel, JavascriptBindingMode.TwoWay), Test = (mb) => { var js = (mb as HtmlBinding).JsBrideRootObject as JsGenericObject; var jsCommand = js.GetAttribute("SimpleCommandNoArgument") as JsSimpleCommand; jsCommand.Should().NotBeNull(); jsCommand.ToString().Should().Be("{}"); jsCommand.Type.Should().Be(JsCsGlueType.SimpleCommand); jsCommand.CachableJsValue.Should().NotBeNull(); } }; await RunAsync(test); }
public async Task TwoWay_Listens_On_CSharp_Side_To_Keys_Added_On_Js_Side() { dynamic dynamicDataContext = new ExpandoObject(); dynamicDataContext.ValueInt = 1; var test = new TestInContextAsync() { Bind = (win) => HtmlBinding.Bind(win, dynamicDataContext, JavascriptBindingMode.TwoWay), Test = async(mb) => { var js = mb.JsRootObject; var Vue = _WebView.GetGlobal().GetValue("Vue"); Vue.InvokeNoResult("set", _WebView, js, _WebView.Factory.CreateString("ValueDouble"), _WebView.Factory.CreateDouble(49)); DoSafeUI(() => { dynamicDataContext.ValueDouble = 659; }); await Task.Delay(50); var resDouble = GetDoubleAttribute(js, "ValueDouble"); resDouble.Should().Be(659); } }; await RunAsync(test); }
public async Task TwoWay_Listens_To_Property_Update_During_Property_Changes_Update_From_Js() { var dataContext = new PropertyUpdatingTestViewModel(); var test = new TestInContextAsync() { Bind = (win) => HtmlBinding.Bind(win, dataContext, JavascriptBindingMode.TwoWay), Test = async(mb) => { var js = mb.JsRootObject; var res = GetStringAttribute(js, "Property1"); res.Should().Be("1"); res = GetStringAttribute(js, "Property2"); res.Should().Be("2"); SetAttribute(js, "Property1", _WebView.Factory.CreateString("a")); await Task.Delay(100); res = GetStringAttribute(js, "Property1"); res.Should().Be("a"); res = GetStringAttribute(js, "Property2"); res.Should().Be("a", "Neutronium listen to object during update"); } }; await RunAsync(test); }
public async Task TwoWay_Collection_Updates_After_ReplaceRange_One_Collection_Changes() { var dataContext = new VmWithRangeCollection <int>(); dataContext.List.AddRange(new[] { 100, 200 }); var test = new TestInContextAsync() { Bind = (win) => HtmlBinding.Bind(win, dataContext, JavascriptBindingMode.TwoWay), Test = async(mb) => { var js = mb.JsRootObject; await DoSafeAsyncUI(() => { dataContext.List.ReplaceRange(new[] { 1, 2, 3, 4, 5 }); }); var col = await GetCollectionAttributeAsync(js, "List"); col.Should().NotBeNull(); CheckIntCollection(col, new[] { 1, 2, 3, 4, 5 }); } }; await RunAsync(test); }
public async Task TwoWay_Maps_CommandGeneric_CanExecuteValue_With_CanExecute(bool canExecute) { var command = Substitute.For <ICommand <string> >(); command.CanExecute(Arg.Any <string>()).Returns(canExecute); var fakeTestViewModel = new FakeTestViewModel() { CommandGenericNotBound = command }; var test = new TestInContext() { Bind = (win) => HtmlBinding.Bind(win, fakeTestViewModel, JavascriptBindingMode.TwoWay), Test = (mb) => { var js = mb.JsRootObject; var jsCommand = GetAttribute(js, "CommandGenericNotBound"); var res = GetBoolAttribute(jsCommand, "CanExecuteValue"); res.Should().BeTrue(); } }; await RunAsync(test); }
public async Task TwoWay_Updates_Collection() { var datacontext = new ChangingCollectionViewModel(); var test = new TestInContextAsync() { Bind = (win) => HtmlBinding.Bind(win, datacontext, JavascriptBindingMode.TwoWay), Test = async(mb) => { var js = mb.JsRootObject; var col = await GetCollectionAttributeAsync(js, "Items"); col.GetArrayLength().Should().NotBe(0); await DoSafeAsyncUIFullCycle(() => datacontext.Replace.Execute(null)); datacontext.Items.Should().BeEmpty(); col = await GetCollectionAttributeAsync(js, "Items"); col.GetArrayLength().Should().Be(0); } }; await RunAsync(test); }
public async Task TwoWay_CommandGeneric_Can_Be_Called_With_Parameter(string parameter) { var command = Substitute.For <ICommand <string> >(); var fakeTestViewModel = new FakeTestViewModel() { CommandGeneric = command }; var test = new TestInContextAsync() { Bind = (win) => HtmlBinding.Bind(win, fakeTestViewModel, JavascriptBindingMode.TwoWay), Test = async(mb) => { var js = mb.JsRootObject; var jsCommand = GetAttribute(js, "CommandGeneric"); var jsParameter = (parameter != null) ? _WebView.Factory.CreateString(parameter) : _WebView.Factory.CreateNull(); await DoSafeAsync(() => Call(jsCommand, "Execute", jsParameter)); await DoSafeAsyncUI(() => command.Received(1).Execute(parameter)); } }; await RunAsync(test); }
public async Task TwoWay_Listens_To_Nested_Changes_After_Property_Updates_Javascript_Updates() { _DataContext.MainSkill.Should().BeNull(); var test = new TestInContextAsync() { Bind = (win) => HtmlBinding.Bind(win, _DataContext, JavascriptBindingMode.TwoWay), Test = async(mb) => { var local = new Local { City = "JJC" }; await DoSafeAsyncUI(() => { _DataContext.Local = local; }); var js = mb.JsRootObject; var jsLocal = await GetAttributeAsync(js, nameof(_DataContext.Local)); var stringName = Create(() => _WebView.Factory.CreateString("Floripa")); await SetAttributeAsync(jsLocal, "City", stringName); await WaitOneCompleteCycle(); await DoSafeAsyncUI(() => _DataContext.Local.City.Should().Be("Floripa")); } }; await RunAsync(test); }
public async Task TwoWay_Command_Generic_Updates_From_Null() { var command = Substitute.For <ICommand <string> >(); var fakeTestViewModel = new FakeTestViewModel(); var argument = "argument"; var test = new TestInContextAsync() { Bind = (win) => HtmlBinding.Bind(win, fakeTestViewModel, JavascriptBindingMode.TwoWay), Test = async(mb) => { var js = mb.JsRootObject; var jsCommand = GetAttribute(js, "Command"); jsCommand.IsNull.Should().BeTrue(); await DoSafeAsyncUI(() => fakeTestViewModel.CommandGeneric = command); jsCommand = await GetAttributeAsync(js, "CommandGeneric"); await DoSafeAsync(() => Call(jsCommand, "Execute", _WebView.Factory.CreateString(argument))); await DoSafeAsyncUI(() => command.Received().Execute(argument)); } }; 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_Command_Is_Updated_When_CanExecute_Changes() { var canExecute = true; _Command.CanExecute(Arg.Any <object>()).ReturnsForAnyArgs(x => canExecute); var test = new TestInContextAsync() { Bind = (win) => HtmlBinding.Bind(win, _DataContext, JavascriptBindingMode.TwoWay), Test = async(mb) => { var js = mb.JsRootObject; var jsCommand = GetAttribute(js, "TestCommand"); var res = GetBoolAttribute(jsCommand, "CanExecuteValue"); res.Should().BeTrue(); canExecute = false; await DoSafeAsyncUI(() => { _Command.CanExecuteChanged += Raise.EventWith(_Command, new EventArgs()); }); jsCommand = await GetAttributeAsync(js, "TestCommand"); res = GetBoolAttribute(jsCommand, "CanExecuteValue"); ((bool)res).Should().BeFalse(); } }; await RunAsync(test); }
public async Task TwoWay_Listens_To_Property_Update_During_Property_Changes_Update_From_Csharp() { var dataContext = new PropertyUpdatingTestViewModel(); var test = new TestInContextAsync() { Bind = (win) => HtmlBinding.Bind(win, dataContext, JavascriptBindingMode.TwoWay), Test = async(mb) => { var js = mb.JsRootObject; var res = GetStringAttribute(js, "Property1"); res.Should().Be("1"); res = GetStringAttribute(js, "Property2"); res.Should().Be("2"); await DoSafeAsyncUI(() => { dataContext.Property1 = "a"; }); res = await GetStringAttributeAsync(js, "Property1"); res.Should().Be("a"); res = GetStringAttribute(js, "Property2"); res.Should().Be("a", "Neutronium listen to object during update"); } }; await RunAsync(test); }
public async Task TwoWay_Command_Does_Not_Throw_When_CanExecute_Throws_exception() { _Command.CanExecute(Arg.Any <object>()).Returns(x => { if (x[0] == null) { throw new Exception(); } return(false); }); var test = new TestInContextAsync() { Bind = (win) => HtmlBinding.Bind(win, _DataContext, JavascriptBindingMode.TwoWay), Test = async(mb) => { _Command.Received().CanExecute(Arg.Any <object>()); var js = mb.JsRootObject; var jsCommand = await GetAttributeAsync(js, "TestCommand"); bool res = GetBoolAttribute(jsCommand, "CanExecuteValue"); res.Should().BeFalse(); _Command.Received().CanExecute(_DataContext); } }; await RunAsync(test); }
public async Task Stress_Big_Vm_Commands(int commandsCount) { var root = new CommandsTestViewModel(); var test = new TestInContextAsync() { Bind = (win) => HtmlBinding.Bind(win, root, JavascriptBindingMode.TwoWay), Test = async(mb) => { var js = mb.JsRootObject; var commands = Enumerable.Range(0, commandsCount).Select(_ => NSubstitute.Substitute.For <ICommand>()).ToArray(); using (var perf = GetPerformanceCounter($"Perf to create Vm with {commandsCount} commands")) { perf.DiscountTime = DelayForTimeOut; await DoSafeAsyncUI(() => root.Commands = commands); await WaitAnotherUiCycleAsync(); await Task.Delay(DelayForTimeOut); var other = await _WebView.EvaluateAsync(() => GetAttribute(js, "Commands")); other.IsArray.Should().BeTrue(); } } }; await RunAsync(test); }
public async Task TwoWay_Command_Round_Trip() { _Command = new RelaySimpleCommand(() => { _DataContext.MainSkill = new Skill(); _DataContext.Skills.Add(_DataContext.MainSkill); }); _DataContext.TestCommand = _Command; var test = new TestInContextAsync() { Bind = (win) => HtmlBinding.Bind(win, _DataContext, JavascriptBindingMode.TwoWay), Test = async(mb) => { var js = mb.JsRootObject; _DataContext.Skills.Should().HaveCount(2); await DoSafeAsyncUIFullCycle(() => { _Command.Execute(null); }); var res = await GetCollectionAttributeAsync(js, "Skills"); res.Should().NotBeNull(); res.GetArrayLength().Should().Be(3); } }; await RunAsync(test); }
public async Task TwoWay_Listens_On_CSharp_Side_To_Keys_Added_On_CSharp_Side() { dynamic dynamicDataContext = new ExpandoObject(); dynamicDataContext.ValueInt = 1; var test = new TestInContextAsync() { Bind = (win) => HtmlBinding.Bind(win, dynamicDataContext, JavascriptBindingMode.TwoWay), Test = async(mb) => { var js = mb.JsRootObject; DoSafeUI(() => { dynamicDataContext.ValueDouble = 0.5; }); await Task.Delay(50); DoSafeUI(() => { dynamicDataContext.ValueDouble = 23; }); await Task.Delay(50); var resDouble = GetDoubleAttribute(js, "ValueDouble"); resDouble.Should().Be(23); } }; await RunAsync(test); }
public async Task TwoWay_ResultCommand_Without_Argument_Returns_Result() { var result = "resultString"; var function = Substitute.For <Func <string> >(); function.Invoke().Returns(result); var dc = new FakeFactory <string>(function); var test = new TestInContextAsync() { Path = TestContext.IndexPromise, Bind = (win) => HtmlBinding.Bind(win, dc, JavascriptBindingMode.TwoWay), Test = async(mb) => { var js = mb.JsRootObject; var jsCommand = GetAttribute(js, "CreateObject"); var cb = GetCallBackObject(); await CallWithResAsync(jsCommand, "Execute", cb); await WaitAnotherWebContextCycle(); var resValue = _WebView.GetGlobal().GetValue("res"); var originalValue = resValue.GetStringValue(); originalValue.Should().Be(result); } }; await RunAsync(test); }
public async Task TwoWay_Listens_On_Js_Side_To_Keys_Added_On_Js_Side() { dynamic dynamicDataContext = new ExpandoObject(); dynamicDataContext.ValueInt = 1; var test = new TestInContextAsync() { Bind = (win) => HtmlBinding.Bind(win, dynamicDataContext, JavascriptBindingMode.TwoWay), Test = async(mb) => { var js = mb.JsRootObject; AddAttribute(js, "ValueDouble", _WebView.Factory.CreateDouble(49)); await Task.Delay(50); SetAttribute(js, "ValueDouble", _WebView.Factory.CreateDouble(7)); await Task.Delay(50); DoSafeUI(() => { double value = dynamicDataContext.ValueDouble; value.Should().Be(7); }); } }; await RunAsync(test); }
public async Task TwoWay_Command_Does_Not_Throw_When_Command_Is_Misused() { var test = new TestInContextAsync() { Bind = (win) => HtmlBinding.Bind(win, _DataContext, JavascriptBindingMode.TwoWay), Test = async(mb) => { await Task.Delay(100); DoSafeUI(() => { _Command.CanExecuteChanged += Raise.Event <EventHandler>(null, new EventArgs()); }); await Task.Delay(100); await WaitAnotherUiCycleAsync(); await Task.Delay(100); } }; Func <Task> @do = () => RunAsync(test); await @do.Should().NotThrowAsync(); }