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);
            });
        }
Beispiel #2
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);
        }
        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_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 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);
        }
Beispiel #10
0
 /// <summary>
 /// Handles async click events by invoking the async <paramref name="handler"/>
 /// </summary>
 /// <param name="handler">The async handler to be invoked when the event occurs.</param>
 /// <returns></returns>
 protected RenderTreeFrame onclickAsync(Func <Task> handler)
 {
     return(RenderTreeFrame.Attribute(0, "onclick", _ =>
     {
         // Run handler and handle any exceptions when any occurs.
         handler().ContinueWith(task =>
         {
             if (task.Exception == null)
             {
                 StateHasChanged();
             }
             else
             {
                 HandleException(task.Exception);
             }
         });
     }));
 }
        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));
        }
Beispiel #14
0
 /// <summary>
 /// Handles click events by invoking <paramref name="handler"/>.
 /// </summary>
 /// <param name="handler">The handler to be invoked when the event occurs.</param>
 /// <returns>A <see cref="RenderTreeFrame"/> that represents the event handler.</returns>
 protected RenderTreeFrame onclick(Action handler)
 // Note that the 'sequence' value is updated later when inserted into the tree
 => RenderTreeFrame.Attribute(0, "onclick", _ => handler());
        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));
        }
Beispiel #16
0
    /// <summary>
    /// Adds a parameter.
    /// </summary>
    /// <param name="name">The name of the parameter.</param>
    /// <param name="value">The value of the parameter.</param>
    public void Add(string name, object?value)
    {
        var nextIndex = _frames[0].ElementSubtreeLengthField++;

        _frames[nextIndex] = RenderTreeFrame.Attribute(0, name, value);
    }
Beispiel #17
0
 /// <summary>
 /// Handles change events by invoking <paramref name="handler"/>.
 /// </summary>
 /// <param name="handler">The handler to be invoked when the event occurs. The handler will receive the new value as a parameter.</param>
 /// <returns>A <see cref="RenderTreeFrame"/> that represents the event handler.</returns>
 protected RenderTreeFrame onchange(Action <object> handler)
 // Note that the 'sequence' value is updated later when inserted into the tree
 => RenderTreeFrame.Attribute(0, "onchange", args => handler(((UIChangeEventArgs)args).Value));