Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Testing components with Telerik Grid throws System.InvalidOperationException #38

Closed
jpiell opened this issue Jan 21, 2020 · 19 comments
Closed
Labels
bug Something isn't working enhancement New feature or request question Further information is requested

Comments

@jpiell
Copy link

jpiell commented Jan 21, 2020

I am testing a component that uses the Telerik UI Blazor grid component. The grid component throws an exception: Message=Cannot provide a value for property 'State' on type 'Telerik.Blazor.Components.TelerikGrid, There is no registered service of type 'Telerik.Blazor.Components.Grid.State.IGridState'.

IGridState is private so it cannot be mocked.

I would like some help on how to work around this issue.

Attached is a sample app I put together to demonstrate the issue I am having.

SampleApp.zip

@egil egil added the question Further information is requested label Jan 21, 2020
@egil
Copy link
Member

egil commented Jan 21, 2020

Hi @jpiell

I will take a look later tonight if time allows, otherwise tomorrow.

@jpiell
Copy link
Author

jpiell commented Jan 21, 2020 via email

@EdCharbeneau
Copy link
Contributor

@jpiell Hi, I work for Telerik. Sorry you're having trouble getting this set up. Because Blazor is new (still in preview), we haven't checked it against all integration points yet, this great testing framework by @egil is the perfect example.

We are evaluating how we can provide better support for this, and I'm testing myself as well.

Short term solution
I believe that if TestServiceProvider implemented IServiceCollection then one could simply call Services.AddTeleirkBlazor() and that would solve the issue. This appears to be on the roadmap here.

Long term solution
This also seems to be the only Telerik service that is set to private. I will forward this to the engineering team and see what the reason is and if it's possible to open up the interface. However, this will likely not change in the immediate future as it would need to be tested and queued for release. If you would like to track this, I would suggest making an entry on our feedback portal.

@egil egil added bug Something isn't working enhancement New feature or request labels Jan 22, 2020
@egil
Copy link
Member

egil commented Jan 22, 2020

@jpiell #39 should be fixed in the upcoming beta 5 release. My plan is to push that out in a day or two, so hopefully that will solve your issue.

@egil egil closed this as completed Jan 22, 2020
@jpiell
Copy link
Author

jpiell commented Jan 22, 2020 via email

@jpiell
Copy link
Author

jpiell commented Jan 22, 2020 via email

@jpiell
Copy link
Author

jpiell commented Jan 23, 2020

Egil,

You need to expose the IServiceCollection or we will not be able to register services.

Thanks,

Jeff

@egil
Copy link
Member

egil commented Jan 23, 2020

Egil,

You need to expose the IServiceCollection or we will not be able to register services.

Thanks,

Jeff

jpiell, in beta-5, TestServiceProvider, available through the Services property in the test context, is a IServiceCollection.

I just did a dotnet new razortest with beta-5, and it looks as if it works as it should. This is my test file:

using System;
using Xunit;
using Egil.RazorComponents.Testing;
using Egil.RazorComponents.Testing.Diffing;
using Egil.RazorComponents.Testing.Asserting;
using Egil.RazorComponents.Testing.Mocking.JSInterop;
using Egil.RazorComponents.Testing.EventDispatchExtensions;
using Microsoft.Extensions.DependencyInjection;

namespace tspsc
{
  public class Component1Test : ComponentTestFixture
  {
    [Fact]
    public void Component1RendersCorrectly()
    {
      Services.AddMySrvs();
      var cut = RenderComponent<Component1>();      

      cut.MarkupMatches(@"<div class=""my-component"">
                            This Blazor component is defined in the <strong>razorclasslib1</strong> package.
                          </div>");
    }
  }

  public static class SrvColExt 
  {
    public static void AddMySrvs(this IServiceCollection services)
    {
      services.AddSingleton(new object());
    }
  }
}

And in razor based tests:

@inherits TestComponentBase

<Fixture Setup="() => Services.AddMySrvs()">
    <ComponentUnderTest><Component1/></ComponentUnderTest>
</Fixture>

Both files compile and run on my computer.

@egil
Copy link
Member

egil commented Jan 23, 2020

It looks as if Teleriks ServiceCollectionExtensions class matches the SrvColExt class in my comment above (https://docs.telerik.com/blazor-ui/api/Microsoft.Extensions.DependencyInjection.ServiceCollectionExtensions.html), so it should work.

Am I missing something here?

@egil
Copy link
Member

egil commented Jan 23, 2020

OK, so I installed into my testing project: <PackageReference Include="Telerik.UI.for.Blazor.Trial" Version="2.6.1" />

Afterwords, both cs and razor tests compile and execute:

using Xunit;
using Egil.RazorComponents.Testing;
using Egil.RazorComponents.Testing.Asserting;
using Microsoft.Extensions.DependencyInjection;

namespace tspsc
{
    public class Component1Test : ComponentTestFixture
    {
        [Fact]
        public void Component1RendersCorrectly()
        {
            Services.AddMySrvs();
            Services.AddTelerikBlazor();

            var cut = RenderComponent<Component1>();

            cut.MarkupMatches(@"<div class=""my-component"">
                            This Blazor component is defined in the <strong>razorclasslib1</strong> package.
                          </div>");
        }
    }

    public static class SrvColExt
    {
        public static void AddMySrvs(this IServiceCollection services)
        {
            services.AddSingleton(new object());
        }
    }
}
@inherits TestComponentBase

<Fixture Setup="() => Services.AddTelerikBlazor()">
    <ComponentUnderTest><Component1/></ComponentUnderTest>
</Fixture>

@jpiell
Copy link
Author

jpiell commented Jan 23, 2020

Do I need to do something other than update my NuGet package?

@egil
Copy link
Member

egil commented Jan 23, 2020

Not entirely sure. But if you follow the guide here: https://github.com/egil/razor-components-testing-library/wiki/Creating-a-new-test-project

Install the template, and the use the dotnet new razortest command, you should end up with a project where you can get my examples above working. Then you can compare and contrast with your existing.

That said, going to beta-5 should be enough, but you might also have to change/add some imports.

@jpiell
Copy link
Author

jpiell commented Jan 23, 2020

All is good now - Thanks again for your help!

@jpiell jpiell closed this as completed Jan 23, 2020
@EdCharbeneau
Copy link
Contributor

@jpiell I was able to verify that a cut could render a Telerik Grid.

@inherits TestComponentBase
@using Microsoft.AspNetCore.Components.Web
@using Egil.RazorComponents.Testing
@using Egil.RazorComponents.Testing.Diffing
@using Egil.RazorComponents.Testing.Asserting
@using Egil.RazorComponents.Testing.EventDispatchExtensions
@using Xunit
@using Telerik.Blazor.Components
@using Microsoft.Extensions.DependencyInjection;

<Fixture Test="Test1">
    <ComponentUnderTest>
        <TelerikRootComponent>
            <TelerikGrid Data="forecasts">
                <GridColumns>
                    <GridColumn Field="@nameof(WeatherForecast.Date)"></GridColumn>
                </GridColumns>
            </TelerikGrid>
        </TelerikRootComponent>
    </ComponentUnderTest>
</Fixture>
@code {

    WeatherForecast[] forecasts = new List<WeatherForecast>().ToArray();

    public void AddTelerikBlazor()
    {
        Services.AddMockJsRuntime();
        Services.AddTelerikBlazor();

}

    void Test1()
    {
        AddTelerikBlazor();

        var cut = GetComponentUnderTest();

        Assert.NotNull(cut);
    }

    public class WeatherForecast
    {
        public DateTime Date { get; set; }

        public int TemperatureC { get; set; }

        public string Summary { get; set; }

        public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
    }
}

@jpiell
Copy link
Author

jpiell commented Jan 23, 2020

@jpiell Hi, I work for Telerik. Sorry you're having trouble getting this set up. Because Blazor is new (still in preview), we haven't checked it against all integration points yet, this great testing framework by @egil is the perfect example.

We are evaluating how we can provide better support for this, and I'm testing myself as well.

Short term solution
I believe that if TestServiceProvider implemented IServiceCollection then one could simply call Services.AddTeleirkBlazor() and that would solve the issue. This appears to be on the roadmap here.

Long term solution
This also seems to be the only Telerik service that is set to private. I will forward this to the engineering team and see what the reason is and if it's possible to open up the interface. However, this will likely not change in the immediate future as it would need to be tested and queued for release. If you would like to track this, I would suggest making an entry on our feedback portal.

Hi Ed,

Would you happen to have any advice on how to get around:

@inherits LayoutComponentBase

    <TelerikRootComponent>

        <div class="sidebar">
            <NavMenu />
        </div>

        <div class="main">
            @Body
        </div>

    </TelerikRootComponent>

My tests are c# only.

Thanks,

Jeff Piell

@EdCharbeneau
Copy link
Contributor

@jpiell

I believe this is the right start. However, I don't know how the various templates are described. @egil ??
Reference markup

        <TelerikRootComponent> (cascading value)
            <TelerikGrid Data="forecasts"> (component<T> parameter Data)
                <GridColumns> (parameter of TelerikGrid)
                    <GridColumn Field="@nameof(WeatherForecast.Date)"></GridColumn> (GridColumn component cascading value from TelerikGrid, parameter Field)
                </GridColumns>
            </TelerikGrid>
        </TelerikRootComponent>
using Egil.RazorComponents.Testing;
using Xunit;
using Telerik.Blazor.Components;
using Microsoft.Extensions.DependencyInjection;
using System;

public class CounterTest : ComponentTestFixture
{
    [Fact]
    public void InitialHtmlIsCorrect()
    {
        Services.AddMockJsRuntime();
        Services.AddTelerikBlazor();
        // Arrange - renders the Counter component
        var root = new TelerikRootComponent();
        var cut = RenderComponent<TelerikGrid<WeatherForecast>>(
            CascadingValue(root));
        Assert.NotNull(cut);
    }

    public class WeatherForecast
    {
        public DateTime Date { get; set; }

        public int TemperatureC { get; set; }

        public string Summary { get; set; }

        public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
    }
}

@jpiell
Copy link
Author

jpiell commented Jan 24, 2020 via email

@jpiell
Copy link
Author

jpiell commented Jan 30, 2020

Ed,

The example doesn't populate the grid.

See the cut.Markup below:

<div id="840207f6-cc00-4007-aab4-bb4e5b86f403" class="k-grid k-widget telerik-blazor" style="" __internal_stopPropagation_onkeydown>


    <div class="k-grid-header" id="ac16a65b-ddff-41bf-b45d-5959cd7d9fdd" role="presentation">
<div class="k-grid-header-wrap" role="presentation">
    <table role="grid" style="width: ;">
        <colgroup role="presentation">


        </colgroup>
        <thead role="rowgroup">
            <tr role="row" data-render-row-index="0">



            </tr>
        </thead>
    </table>
</div>
    <div class="k-grid-container">
        <div class="k-grid-content k-virtual-content" id="72b5dfe2-5b56-4e8f-8798-bfdb9e1db4eb">
<div style="position: relative;">
    <div class="k-virtual-position" style="" data-translate="0" data-total="0">
        
            <table data-role="grid" role="grid" class="k-grid-table" style="height: auto; width: ;" aria-rowcount="0" aria-colcount="0">
                <colgroup>


                </colgroup>
                <tbody role="rowgroup">





                </tbody>
            </table>
        
    </div>
</div>
<div class="k-height-container">
    <div style=""></div>
</div>
</div>

@jpiell
Copy link
Author

jpiell commented Jan 30, 2020

@jpiell I was able to verify that a cut could render a Telerik Grid.

@inherits TestComponentBase
@using Microsoft.AspNetCore.Components.Web
@using Egil.RazorComponents.Testing
@using Egil.RazorComponents.Testing.Diffing
@using Egil.RazorComponents.Testing.Asserting
@using Egil.RazorComponents.Testing.EventDispatchExtensions
@using Xunit
@using Telerik.Blazor.Components
@using Microsoft.Extensions.DependencyInjection;

<Fixture Test="Test1">
    <ComponentUnderTest>
        <TelerikRootComponent>
            <TelerikGrid Data="forecasts">
                <GridColumns>
                    <GridColumn Field="@nameof(WeatherForecast.Date)"></GridColumn>
                </GridColumns>
            </TelerikGrid>
        </TelerikRootComponent>
    </ComponentUnderTest>
</Fixture>
@code {

    WeatherForecast[] forecasts = new List<WeatherForecast>().ToArray();

    public void AddTelerikBlazor()
    {
        Services.AddMockJsRuntime();
        Services.AddTelerikBlazor();

}

    void Test1()
    {
        AddTelerikBlazor();

        var cut = GetComponentUnderTest();

        Assert.NotNull(cut);
    }

    public class WeatherForecast
    {
        public DateTime Date { get; set; }

        public int TemperatureC { get; set; }

        public string Summary { get; set; }

        public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
    }
}

It should actually be:

        var cut = RenderComponent<TelerikRootComponent>(
            ChildContent<FetchData>(
            ));

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working enhancement New feature or request question Further information is requested
Projects
None yet
Development

No branches or pull requests

3 participants