public async Task ThrowsIfWeReceiveAnOutOfSequenceClientAcknowledge()
        {
            // Arrange
            var serviceProvider = new ServiceCollection().BuildServiceProvider();
            var firstBatchTCS   = new TaskCompletionSource <object>();
            var secondBatchTCS  = new TaskCompletionSource <object>();
            var offlineClient   = new CircuitClientProxy(new Mock <IClientProxy>(MockBehavior.Strict).Object, "offline-client");

            offlineClient.SetDisconnected();
            var            renderer       = GetRemoteRenderer(serviceProvider, offlineClient);
            RenderFragment initialContent = (builder) =>
            {
                builder.OpenElement(0, "my element");
                builder.AddContent(1, "some text");
                builder.CloseElement();
            };
            var trigger      = new Trigger();
            var renderIds    = new List <long>();
            var onlineClient = new Mock <IClientProxy>();

            onlineClient.Setup(c => c.SendCoreAsync(It.IsAny <string>(), It.IsAny <object[]>(), It.IsAny <CancellationToken>()))
            .Callback((string name, object[] value, CancellationToken token) => renderIds.Add((long)value[1]))
            .Returns <string, object[], CancellationToken>((n, v, t) => (long)v[1] == 2 ? firstBatchTCS.Task : secondBatchTCS.Task);

            // This produces the initial batch (id = 2)
            var result = await renderer.RenderComponentAsync <AutoParameterTestComponent>(
                ParameterCollection.FromDictionary(new Dictionary <string, object>
            {
                [nameof(AutoParameterTestComponent.Content)] = initialContent,
                [nameof(AutoParameterTestComponent.Trigger)] = trigger
            }));

            trigger.Component.Content = (builder) =>
            {
                builder.OpenElement(0, "offline element");
                builder.AddContent(1, "offline text");
                builder.CloseElement();
            };
            // This produces an additional batch (id = 3)
            trigger.TriggerRender();
            var originallyQueuedBatches = renderer.PendingRenderBatches.Count;

            // Act
            offlineClient.Transfer(onlineClient.Object, "new-connection");
            var task       = renderer.ProcessBufferedRenderBatches();
            var exceptions = new List <Exception>();

            renderer.UnhandledException += (sender, e) =>
            {
                exceptions.Add(e);
            };

            // Pretend that we missed the ack for the initial batch
            renderer.OnRenderCompleted(3, null);
            firstBatchTCS.SetResult(null);
            secondBatchTCS.SetResult(null);

            // Assert
            var exception = Assert.Single(exceptions);
        }
Beispiel #2
0
        public async Task ProcessBufferedRenderBatches_WritesRenders()
        {
            // Arrange
            var serviceProvider = new ServiceCollection().BuildServiceProvider();
            var renderIds       = new List <long>();

            var firstBatchTCS  = new TaskCompletionSource <object>();
            var secondBatchTCS = new TaskCompletionSource <object>();
            var thirdBatchTCS  = new TaskCompletionSource <object>();

            var initialClient = new Mock <IClientProxy>();

            initialClient.Setup(c => c.SendCoreAsync(It.IsAny <string>(), It.IsAny <object[]>(), It.IsAny <CancellationToken>()))
            .Callback((string name, object[] value, CancellationToken token) => renderIds.Add((long)value[1]))
            .Returns(firstBatchTCS.Task);
            var circuitClient = new CircuitClientProxy(initialClient.Object, "connection0");
            var renderer      = GetRemoteRenderer(serviceProvider, circuitClient);
            var component     = new TestComponent(builder =>
            {
                builder.OpenElement(0, "my element");
                builder.AddContent(1, "some text");
                builder.CloseElement();
            });

            var client = new Mock <IClientProxy>();

            client.Setup(c => c.SendCoreAsync(It.IsAny <string>(), It.IsAny <object[]>(), It.IsAny <CancellationToken>()))
            .Callback((string name, object[] value, CancellationToken token) => renderIds.Add((long)value[1]))
            .Returns <string, object[], CancellationToken>((n, v, t) => (long)v[1] == 3 ? secondBatchTCS.Task : thirdBatchTCS.Task);

            var componentId = renderer.AssignRootComponentId(component);

            component.TriggerRender();
            renderer.OnRenderCompleted(2, null);
            firstBatchTCS.SetResult(null);

            circuitClient.SetDisconnected();
            component.TriggerRender();
            component.TriggerRender();

            // Act
            circuitClient.Transfer(client.Object, "new-connection");
            var task = renderer.ProcessBufferedRenderBatches();

            foreach (var id in renderIds.ToArray())
            {
                renderer.OnRenderCompleted(id, null);
            }

            secondBatchTCS.SetResult(null);
            thirdBatchTCS.SetResult(null);

            // Assert
            Assert.Equal(new long[] { 2, 3, 4 }, renderIds);
            Assert.True(task.Wait(3000), "One or more render batches werent acknowledged");

            await task;
        }
        public async Task ProcessBufferedRenderBatches_WritesRenders()
        {
            // Arrange
            var serviceProvider = new ServiceCollection().BuildServiceProvider();
            var renderIds       = new List <int>();

            var initialClient = new Mock <IClientProxy>();

            initialClient.Setup(c => c.SendCoreAsync(It.IsAny <string>(), It.IsAny <object[]>(), It.IsAny <CancellationToken>()))
            .Callback((string name, object[] value, CancellationToken token) =>
            {
                renderIds.Add((int)value[1]);
            })
            .Returns(Task.CompletedTask);
            var circuitClient = new CircuitClientProxy(initialClient.Object, "connection0");
            var renderer      = GetRemoteRenderer(serviceProvider, circuitClient);
            var component     = new TestComponent(builder =>
            {
                builder.OpenElement(0, "my element");
                builder.AddContent(1, "some text");
                builder.CloseElement();
            });


            var client = new Mock <IClientProxy>();

            client.Setup(c => c.SendCoreAsync(It.IsAny <string>(), It.IsAny <object[]>(), It.IsAny <CancellationToken>()))
            .Callback((string name, object[] value, CancellationToken token) =>
            {
                renderIds.Add((int)value[1]);
            })
            .Returns(Task.CompletedTask);
            var componentId = renderer.AssignRootComponentId(component);

            component.TriggerRender();
            renderer.OnRenderCompleted(1, null);

            circuitClient.SetDisconnected();
            component.TriggerRender();
            component.TriggerRender();

            // Act
            circuitClient.Transfer(client.Object, "new-connection");
            var task = renderer.ProcessBufferedRenderBatches();

            foreach (var id in renderIds)
            {
                renderer.OnRenderCompleted(id, null);
            }
            await task;

            // Assert
            client.Verify(c => c.SendCoreAsync("JS.RenderBatch", It.IsAny <object[]>(), It.IsAny <CancellationToken>()), Times.Exactly(2));
        }
    public void Transfer_SetsConnected()
    {
        // Arrange
        var clientProxy = Mock.Of <IClientProxy>(
            c => c.SendCoreAsync(It.IsAny <string>(), It.IsAny <object[]>(), It.IsAny <CancellationToken>()) == Task.CompletedTask);
        var circuitClient = new CircuitClientProxy(clientProxy, "connection0");

        circuitClient.SetDisconnected();

        // Act
        circuitClient.Transfer(Mock.Of <IClientProxy>(), "connection1");

        // Assert
        Assert.True(circuitClient.Connected);
    }
Beispiel #5
0
        public void IfInitialized_IsConnectedValueDeterminedByCircuitProxy()
        {
            // Arrange
            var clientProxy            = new FakeClientProxy();
            var circuitProxy           = new CircuitClientProxy(clientProxy, "test connection");
            var remoteComponentContext = new RemoteComponentContext();

            // Act/Assert: Can observe connected state
            remoteComponentContext.Initialize(circuitProxy);
            Assert.True(remoteComponentContext.IsConnected);

            // Act/Assert: Can observe disconnected state
            circuitProxy.SetDisconnected();
            Assert.False(remoteComponentContext.IsConnected);
        }