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); }
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); }
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); }