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);
            });
        }
Example #2
0
 /// <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);
 }
Example #3
0
        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);
        }
Example #4
0
    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));
        }
Example #6
0
        /// <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);
        }
Example #13
0
    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));
        }
Example #17
0
        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));
        }