protected private RenderTreeFrame[] GetRenderTree(TestRenderer renderer, IComponent component) { renderer.AttachComponent(component); var task = renderer.InvokeAsync(() => component.SetParametersAsync(ParameterCollection.Empty)); // we will have to change this method if we add a test that does actual async work. Assert.True(task.Status.HasFlag(TaskStatus.RanToCompletion) || task.Status.HasFlag(TaskStatus.Faulted)); if (task.IsFaulted) { ExceptionDispatchInfo.Capture(task.Exception.InnerException).Throw(); } return(renderer.LatestBatchReferenceFrames); }
static CascadingValue <T> CreateCascadingValueComponent <T>(T value, string name = null) { var supplier = new CascadingValue <T>(); var renderer = new TestRenderer(); supplier.Configure(new RenderHandle(renderer, 0)); var supplierParams = new Dictionary <string, object> { { "Value", value } }; if (name != null) { supplierParams.Add("Name", name); } renderer.InvokeAsync((Action)(() => supplier.SetParametersAsync(ParameterCollection.FromDictionary(supplierParams)))); return(supplier); }
public async Task SupportsTwoWayBindingForDateValues() { // Arrange/Act var component = CompileToComponent( @"<input @bind=""MyDate"" /> @code { public DateTime MyDate { get; set; } = new DateTime(2018, 3, 4, 1, 2, 3); }"); var myDateProperty = component.GetType().GetProperty("MyDate"); var renderer = new TestRenderer(); // Assert EventCallback setter = default; var frames = GetRenderTree(renderer, component); Assert.Collection(frames, frame => AssertFrame.Element(frame, "input", 3, 0), frame => AssertFrame.Attribute(frame, "value", new DateTime(2018, 3, 4, 1, 2, 3).ToString(), 1), frame => { AssertFrame.Attribute(frame, "onchange", 2); setter = Assert.IsType <EventCallback>(frame.AttributeValue); }); // Trigger the change event to show it updates the property // Trigger the change event to show it updates the property // // This should always complete synchronously. var newDateValue = new DateTime(2018, 3, 5, 4, 5, 6); var task = renderer.InvokeAsync(() => setter.InvokeAsync(new UIChangeEventArgs { Value = newDateValue.ToString(), })); Assert.Equal(TaskStatus.RanToCompletion, task.Status); await task; Assert.Equal(newDateValue, myDateProperty.GetValue(component)); }
public async Task SupportsTwoWayBindingForEnumValues() { // Arrange/Act var myEnumType = FullTypeName <MyEnum>(); var component = CompileToComponent( $@"<input @bind=""MyValue"" /> @code {{ public {myEnumType} MyValue {{ get; set; }} = {myEnumType}.{nameof(MyEnum.FirstValue)}; }}"); var myValueProperty = component.GetType().GetProperty("MyValue"); var renderer = new TestRenderer(); // Assert EventCallback setter = default; var frames = GetRenderTree(renderer, component); Assert.Collection(frames, frame => AssertFrame.Element(frame, "input", 3, 0), frame => AssertFrame.Attribute(frame, "value", MyEnum.FirstValue.ToString(), 1), frame => { AssertFrame.Attribute(frame, "onchange", 2); setter = Assert.IsType <EventCallback>(frame.AttributeValue); }); // Trigger the change event to show it updates the property // // This should always complete synchronously. var task = renderer.InvokeAsync(() => setter.InvokeAsync(new UIChangeEventArgs { Value = MyEnum.SecondValue.ToString(), })); Assert.Equal(TaskStatus.RanToCompletion, task.Status); await task; Assert.Equal(MyEnum.SecondValue, (MyEnum)myValueProperty.GetValue(component)); }
public async Task SupportsTwoWayBindingForBoolValues() { // Arrange/Act var component = CompileToComponent( @"<input bind=""MyValue"" /> @functions { public bool MyValue { get; set; } = true; }"); var myValueProperty = component.GetType().GetProperty("MyValue"); var renderer = new TestRenderer(); // Assert EventCallback setter = default; var frames = GetRenderTree(renderer, component); Assert.Collection(frames, frame => AssertFrame.Element(frame, "input", 3, 0), frame => AssertFrame.Attribute(frame, "value", true, 1), frame => { AssertFrame.Attribute(frame, "onchange", 2); setter = Assert.IsType <EventCallback>(frame.AttributeValue); }); // Trigger the change event to show it updates the property // // This should always complete synchronously. var task = renderer.InvokeAsync(() => setter.InvokeAsync(new UIChangeEventArgs() { Value = false, })); Assert.Equal(TaskStatus.RanToCompletion, task.Status); await task; Assert.False((bool)myValueProperty.GetValue(component)); }
public async Task SupportsTwoWayBindingForTextareas() { // Arrange/Act var component = CompileToComponent( @"<textarea @bind=""MyValue"" ></textarea> @code { public string MyValue { get; set; } = ""Initial value""; }"); var myValueProperty = component.GetType().GetProperty("MyValue"); var renderer = new TestRenderer(); // Assert EventCallback setter = default; var frames = GetRenderTree(renderer, component); Assert.Collection(frames, frame => AssertFrame.Element(frame, "textarea", 3, 0), frame => AssertFrame.Attribute(frame, "value", "Initial value", 1), frame => { AssertFrame.Attribute(frame, "onchange", 2); setter = Assert.IsType <EventCallback>(frame.AttributeValue); }); // Trigger the change event to show it updates the property // // This should always complete synchronously. var task = renderer.InvokeAsync(() => setter.InvokeAsync(new UIChangeEventArgs { Value = "Modified value", })); Assert.Equal(TaskStatus.RanToCompletion, task.Status); await task; Assert.Equal("Modified value", myValueProperty.GetValue(component)); }