Add unit tests for illegal ParameterView access
This commit is contained in:
parent
2fc604145a
commit
206f793fb5
|
|
@ -354,6 +354,40 @@ namespace Microsoft.AspNetCore.Components.Test
|
|||
Assert.Equal("The value of IsFixed cannot be changed dynamically.", ex.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParameterViewSuppliedWithCascadingParametersCannotBeUsedAfterSynchronousReturn()
|
||||
{
|
||||
// Arrange
|
||||
var providedValue = "Initial value";
|
||||
var renderer = new TestRenderer();
|
||||
var component = new TestComponent(builder =>
|
||||
{
|
||||
builder.OpenComponent<CascadingValue<string>>(0);
|
||||
builder.AddAttribute(1, "Value", providedValue);
|
||||
builder.AddAttribute(2, "ChildContent", new RenderFragment(childBuilder =>
|
||||
{
|
||||
childBuilder.OpenComponent<CascadingParameterConsumerComponent<string>>(0);
|
||||
childBuilder.CloseComponent();
|
||||
}));
|
||||
builder.CloseComponent();
|
||||
});
|
||||
|
||||
// Initial render; capture nested component
|
||||
var componentId = renderer.AssignRootComponentId(component);
|
||||
component.TriggerRender();
|
||||
var firstBatch = renderer.Batches.Single();
|
||||
var nestedComponent = FindComponent<CascadingParameterConsumerComponent<string>>(firstBatch, out var nestedComponentId);
|
||||
|
||||
// Re-render CascadingValue with new value, so it gets a new ParameterView
|
||||
providedValue = "Updated value";
|
||||
component.TriggerRender();
|
||||
Assert.Equal(2, renderer.Batches.Count);
|
||||
|
||||
// It's no longer able to access anything in the ParameterView it just received
|
||||
var ex = Assert.Throws<InvalidOperationException>(nestedComponent.AttemptIllegalAccessToLastParameterView);
|
||||
Assert.Equal("blah", ex.Message);
|
||||
}
|
||||
|
||||
private static T FindComponent<T>(CapturedBatch batch, out int componentId)
|
||||
{
|
||||
var componentFrame = batch.ReferenceFrames.Single(
|
||||
|
|
@ -378,6 +412,8 @@ namespace Microsoft.AspNetCore.Components.Test
|
|||
|
||||
class CascadingParameterConsumerComponent<T> : AutoRenderComponent
|
||||
{
|
||||
private ParameterView lastParameterView;
|
||||
|
||||
public int NumSetParametersCalls { get; private set; }
|
||||
public int NumRenders { get; private set; }
|
||||
|
||||
|
|
@ -386,6 +422,7 @@ namespace Microsoft.AspNetCore.Components.Test
|
|||
|
||||
public override async Task SetParametersAsync(ParameterView parameters)
|
||||
{
|
||||
lastParameterView = parameters;
|
||||
NumSetParametersCalls++;
|
||||
await base.SetParametersAsync(parameters);
|
||||
}
|
||||
|
|
@ -395,6 +432,13 @@ namespace Microsoft.AspNetCore.Components.Test
|
|||
NumRenders++;
|
||||
builder.AddContent(0, $"CascadingParameter={CascadingParameter}; RegularParameter={RegularParameter}");
|
||||
}
|
||||
|
||||
public void AttemptIllegalAccessToLastParameterView()
|
||||
{
|
||||
// You're not allowed to hold onto a ParameterView and access it later,
|
||||
// so this should throw
|
||||
lastParameterView.TryGetValue<object>("anything", out _);
|
||||
}
|
||||
}
|
||||
|
||||
class SecondCascadingParameterConsumerComponent<T1, T2> : CascadingParameterConsumerComponent<T1>
|
||||
|
|
|
|||
|
|
@ -3701,6 +3701,24 @@ namespace Microsoft.AspNetCore.Components.Test
|
|||
Assert.Contains("Cannot start a batch when one is already in progress.", ex.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CannotAccessParameterViewAfterSynchronousReturn()
|
||||
{
|
||||
// Arrange
|
||||
var renderer = new TestRenderer();
|
||||
var component = new ParameterViewIllegalCapturingComponent();
|
||||
var componentId = renderer.AssignRootComponentId(component);
|
||||
renderer.RenderRootComponentAsync(componentId);
|
||||
|
||||
// Act/Assert
|
||||
var ex = Assert.Throws<InvalidOperationException>(() =>
|
||||
{
|
||||
// TODO: check other types of access too
|
||||
component.CapturedParameterView.TryGetValue<object>("anything", out _);
|
||||
});
|
||||
Assert.Equal("blah", ex.Message);
|
||||
}
|
||||
|
||||
private class NoOpRenderer : Renderer
|
||||
{
|
||||
public NoOpRenderer() : base(new TestServiceProvider(), NullLoggerFactory.Instance)
|
||||
|
|
@ -4443,5 +4461,23 @@ namespace Microsoft.AspNetCore.Components.Test
|
|||
public new void ProcessPendingRender()
|
||||
=> base.ProcessPendingRender();
|
||||
}
|
||||
|
||||
class ParameterViewIllegalCapturingComponent : IComponent
|
||||
{
|
||||
public ParameterView CapturedParameterView { get; private set; }
|
||||
|
||||
public void Attach(RenderHandle renderHandle)
|
||||
{
|
||||
}
|
||||
|
||||
public Task SetParametersAsync(ParameterView parameters)
|
||||
{
|
||||
CapturedParameterView = parameters;
|
||||
|
||||
// Return a task that never completes to show that access is forbidded
|
||||
// after the synchronous return, not just after the returned task completes
|
||||
return new TaskCompletionSource<object>().Task;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue