public void CanConvertToReadOnlyDictionary() { // Arrange var entry2Value = new object(); var parameterCollection = new ParameterCollection(new[] { RenderTreeFrame.Element(0, "some element").WithElementSubtreeLength(3), RenderTreeFrame.Attribute(0, "entry 1", "value 1"), RenderTreeFrame.Attribute(0, "entry 2", entry2Value), }, 0); // Act IReadOnlyDictionary <string, object> dict = parameterCollection.ToDictionary(); // Assert Assert.Collection(dict, entry => { Assert.Equal("entry 1", entry.Key); Assert.Equal("value 1", entry.Value); }, entry => { Assert.Equal("entry 2", entry.Key); Assert.Same(entry2Value, entry.Value); }); }
/// <summary> /// Constructs an instance of <see cref="ParameterViewBuilder" />. /// </summary> /// <param name="maxCapacity">The maximum number of parameters that can be held.</param> public ParameterViewBuilder(int maxCapacity) { _frames = new RenderTreeFrame[maxCapacity + 1]; _frames[0] = RenderTreeFrame .Element(0, GeneratedParameterViewElementName) .WithElementSubtreeLength(1); }
public void RenderComponentAsync_CanPassParameters() { // Arrange var expectedHtml = new[] { "<", "p", ">", "<", "input", " ", "value", "=", "\"", "5", "\"", " />", "</", "p", ">" }; RenderFragment Content(ParameterCollection pc) => new RenderFragment((RenderTreeBuilder rtb) => { rtb.OpenElement(0, "p"); rtb.OpenElement(1, "input"); rtb.AddAttribute(2, "change", pc.GetValueOrDefault <Action <UIChangeEventArgs> >("update")); rtb.AddAttribute(3, "value", pc.GetValueOrDefault <int>("value")); rtb.CloseElement(); rtb.CloseElement(); }); var serviceProvider = new ServiceCollection() .AddSingleton(new Func <ParameterCollection, RenderFragment>(Content)) .BuildServiceProvider(); var htmlRenderer = GetHtmlRenderer(serviceProvider); Action <UIChangeEventArgs> change = (UIChangeEventArgs changeArgs) => throw new InvalidOperationException(); // Act var result = GetResult(Dispatcher.InvokeAsync(() => htmlRenderer.RenderComponentAsync <ComponentWithParameters>( new ParameterCollection(new[] { RenderTreeFrame.Element(0, string.Empty), RenderTreeFrame.Attribute(1, "update", change), RenderTreeFrame.Attribute(2, "value", 5) }, 0)))); // Assert Assert.Equal(expectedHtml, result); }
public void CanInitializeUsingElementWithNoDescendants() { // Arrange var frames = new[] { RenderTreeFrame.Element(0, "some element").WithElementSubtreeLength(1) }; var parameters = new ParameterView(ParameterViewLifetime.Unbound, frames, 0); // Assert Assert.Empty(ToEnumerable(parameters)); }
public void CanInitializeUsingElementWithNoDescendants() { // Arrange var frames = new[] { RenderTreeFrame.Element(0, "some element").WithElementSubtreeLength(1) }; var parameterCollection = new ParameterCollection(frames, 0); // Assert Assert.Empty(ToEnumerable(parameterCollection)); }
/// <summary> /// Appends a frame representing an element, i.e., a container for other frames. /// In order for the <see cref="RenderTreeBuilder"/> state to be valid, you must /// also call <see cref="CloseElement"/> immediately after appending the /// new element's child frames. /// </summary> /// <param name="sequence">An integer that represents the position of the instruction in the source code.</param> /// <param name="elementName">A value representing the type of the element.</param> public void OpenElement(int sequence, string elementName) { // We are entering a new scope, since we track the "duplicate attributes" per // element/component we might need to clean them up now. if (_hasSeenAddMultipleAttributes) { var indexOfLastElementOrComponent = _openElementIndices.Peek(); ProcessDuplicateAttributes(first: indexOfLastElementOrComponent + 1); } _openElementIndices.Push(_entries.Count); Append(RenderTreeFrame.Element(sequence, elementName)); }
public void CanGetValueOrDefault_WithNonExistingValue() { // Arrange var parameterCollection = new ParameterCollection(new[] { RenderTreeFrame.Element(0, "some element").WithElementSubtreeLength(2), RenderTreeFrame.Attribute(1, "some other entry", new object()) }, 0); // Act var result = parameterCollection.GetValueOrDefault <DateTime>("nonexisting entry"); // Assert Assert.Equal(default, result);
public void ThrowsIfTryGetExistingValueWithIncorrectType() { // Arrange var parameterCollection = new ParameterCollection(new[] { RenderTreeFrame.Element(0, "some element").WithElementSubtreeLength(2), RenderTreeFrame.Attribute(1, "my entry", "hello") }, 0); // Act/Assert Assert.Throws <InvalidCastException>(() => { parameterCollection.TryGetValue <bool>("my entry", out var value); }); }
public void CanTryGetExistingValueWithCorrectType() { // Arrange var parameterCollection = new ParameterCollection(new[] { RenderTreeFrame.Element(0, "some element").WithElementSubtreeLength(2), RenderTreeFrame.Attribute(1, "my entry", "hello") }, 0); // Act var didFind = parameterCollection.TryGetValue <string>("my entry", out var value); // Assert Assert.True(didFind); Assert.Equal("hello", value); }
public void CanTryGetNonExistingValue() { // Arrange var parameterCollection = new ParameterCollection(new[] { RenderTreeFrame.Element(0, "some element").WithElementSubtreeLength(2), RenderTreeFrame.Attribute(1, "some other entry", new object()) }, 0); // Act var didFind = parameterCollection.TryGetValue <string>("nonexisting entry", out var value); // Assert Assert.False(didFind); Assert.Null(value); }
public void CanGetValueOrDefault_WithMultipleMatchingValues() { // Arrange var myEntryValue = new object(); var parameterCollection = new ParameterCollection(new[] { RenderTreeFrame.Element(0, "some element").WithElementSubtreeLength(3), RenderTreeFrame.Attribute(1, "my entry", myEntryValue), RenderTreeFrame.Attribute(1, "my entry", new object()), }, 0); // Act var result = parameterCollection.GetValueOrDefault <object>("my entry"); // Assert: Picks first match Assert.Same(myEntryValue, result); }
public void CanGetValueOrDefault_WithExistingValue() { // Arrange var myEntryValue = new object(); var parameterCollection = new ParameterCollection(new[] { RenderTreeFrame.Element(0, "some element").WithElementSubtreeLength(2), RenderTreeFrame.Attribute(1, "my entry", myEntryValue), RenderTreeFrame.Attribute(1, "my other entry", new object()) }, 0); // Act var result = parameterCollection.GetValueOrDefault <object>("my entry"); // Assert Assert.Same(myEntryValue, result); }
public void CanGetValueOrDefault_WithNonExistingValue() { // Arrange var parameters = new ParameterView(ParameterViewLifetime.Unbound, new[] { RenderTreeFrame.Element(0, "some element").WithElementSubtreeLength(2), RenderTreeFrame.Attribute(1, "some other entry", new object()) }, 0).WithCascadingParameters(new List <CascadingParameterState> { new CascadingParameterState("another entry", new TestCascadingValue(null)) }); // Act var result = parameters.GetValueOrDefault <DateTime>("nonexisting entry"); // Assert Assert.Equal(default, result);
public void EnumerationStopsAtEndOfOwnerAttributes() { // Arrange var attribute1Value = new object(); var attribute2Value = new object(); var frames = new[] { RenderTreeFrame.Element(0, "some element").WithElementSubtreeLength(3), RenderTreeFrame.Attribute(1, "attribute 1", attribute1Value), RenderTreeFrame.Attribute(2, "attribute 2", attribute2Value), RenderTreeFrame.Element(3, "child element").WithElementSubtreeLength(2), RenderTreeFrame.Attribute(4, "child attribute", "some value") }; var parameterCollection = new ParameterCollection(frames, 0); // Assert Assert.Collection(ToEnumerable(parameterCollection), AssertParameter("attribute 1", attribute1Value), AssertParameter("attribute 2", attribute2Value)); }
public void EnumerationIncludesCascadingParameters() { // Arrange var attribute1Value = new object(); var attribute2Value = new object(); var attribute3Value = new object(); var parameterCollection = new ParameterCollection(new[] { RenderTreeFrame.Element(0, "some element").WithElementSubtreeLength(2), RenderTreeFrame.Attribute(1, "attribute 1", attribute1Value) }, 0).WithCascadingParameters(new List <CascadingParameterState> { new CascadingParameterState("attribute 2", new TestCascadingValue(attribute2Value)), new CascadingParameterState("attribute 3", new TestCascadingValue(attribute3Value)), }); // Assert Assert.Collection(ToEnumerable(parameterCollection), AssertParameter("attribute 1", attribute1Value), AssertParameter("attribute 2", attribute2Value), AssertParameter("attribute 3", attribute3Value)); }
public void EnumerationStopsAtEndOfOwnerDescendants() { // Arrange var attribute1Value = new object(); var attribute2Value = new object(); var frames = new[] { RenderTreeFrame.Element(0, "some element").WithElementSubtreeLength(3), RenderTreeFrame.Attribute(1, "attribute 1", attribute1Value), RenderTreeFrame.Attribute(2, "attribute 2", attribute2Value), // Although RenderTreeBuilder doesn't let you add orphaned attributes like this, // still want to verify that ParameterCollection doesn't attempt to read past the // end of the owner's descendants RenderTreeFrame.Attribute(3, "orphaned attribute", "value") }; var parameterCollection = new ParameterCollection(frames, 0); // Assert Assert.Collection(ToEnumerable(parameterCollection), AssertParameter("attribute 1", attribute1Value), AssertParameter("attribute 2", attribute2Value)); }
private static ArrayRange <RenderTreeFrame> ReadReferenceFrames(ReadOnlySpan <byte> data, string[] strings) { var result = new RenderTreeFrame[data.Length / ReferenceFrameSize]; for (var i = 0; i < data.Length; i += ReferenceFrameSize) { var frameData = data.Slice(i, ReferenceFrameSize); var type = (RenderTreeFrameType)BitConverter.ToInt32(frameData.Slice(0, 4)); // We want each frame to take up the same number of bytes, so that the // recipient can index into the array directly instead of having to // walk through it. // Since we can fit every frame type into 16 bytes, use that as the // common size. For smaller frames, we add padding to expand it to // 16 bytes. switch (type) { case RenderTreeFrameType.Attribute: var attributeName = ReadString(frameData.Slice(4, 4), strings); var attributeValue = ReadString(frameData.Slice(8, 4), strings); var attributeEventHandlerId = BitConverter.ToUInt64(frameData.Slice(12, 8)); result[i / ReferenceFrameSize] = RenderTreeFrame.Attribute(0, attributeName, attributeValue).WithAttributeEventHandlerId(attributeEventHandlerId); break; case RenderTreeFrameType.Component: var componentSubtreeLength = BitConverter.ToInt32(frameData.Slice(4, 4)); var componentId = BitConverter.ToInt32(frameData.Slice(8, 4)); // Nowhere to put this without creating a ComponentState result[i / ReferenceFrameSize] = RenderTreeFrame.ChildComponent(0, componentType: null) .WithComponentSubtreeLength(componentSubtreeLength) .WithComponent(new ComponentState(Renderer, componentId, new FakeComponent(), null)); break; case RenderTreeFrameType.ComponentReferenceCapture: // Client doesn't process these, skip. result[i / ReferenceFrameSize] = RenderTreeFrame.ComponentReferenceCapture(0, null, 0); break; case RenderTreeFrameType.Element: var elementSubtreeLength = BitConverter.ToInt32(frameData.Slice(4, 4)); var elementName = ReadString(frameData.Slice(8, 4), strings); result[i / ReferenceFrameSize] = RenderTreeFrame.Element(0, elementName).WithElementSubtreeLength(elementSubtreeLength); break; case RenderTreeFrameType.ElementReferenceCapture: var referenceCaptureId = ReadString(frameData.Slice(4, 4), strings); result[i / ReferenceFrameSize] = RenderTreeFrame.ElementReferenceCapture(0, null) .WithElementReferenceCaptureId(referenceCaptureId); break; case RenderTreeFrameType.Region: var regionSubtreeLength = BitConverter.ToInt32(frameData.Slice(4, 4)); result[i / ReferenceFrameSize] = RenderTreeFrame.Region(0).WithRegionSubtreeLength(regionSubtreeLength); break; case RenderTreeFrameType.Text: var text = ReadString(frameData.Slice(4, 4), strings); result[i / ReferenceFrameSize] = RenderTreeFrame.Text(0, text); break; case RenderTreeFrameType.Markup: var markup = ReadString(frameData.Slice(4, 4), strings); result[i / ReferenceFrameSize] = RenderTreeFrame.Markup(0, markup); break; default: throw new ArgumentException($"Unsupported frame type: {type}"); } } return(new ArrayRange <RenderTreeFrame>(result, result.Length)); }