How can I write an integration test on an authorize page in a Razor app in order to access and test it?

77 Views Asked by At

I want to make a test that access my page that need Admin role to access it. This is my page: (Model)

    [Authorize(Roles = "Admin")]
    public class AddModel : PageModel
    {
        private readonly ILinkRepository _linkRepository;

        [BindProperty]
        public AddLink AddLinkRequest { get; set; }

        public AddModel(ILinkRepository linkRepository)
        {
            _linkRepository = linkRepository;
        }

        public void OnGet()
        {
            ViewData["Title"] = "Ajouter un lien";
        }

        public async Task<IActionResult> OnPost()
        {
            ...

            return RedirectToPage("/Admin/Links/List");
        }
    }

The view is this:

@page
@model as_quebec.Pages.Admin.Links.AddModel
@{
}

<div class="bg-secondary bg-opacity-10 py-2 mb-5">
    <div class="container">
        <h1 id="title">Ajouter un lien</h1>
    </div>
</div>

<div>
    ...        
</div>

So here is my test that doesn't pass (I get 302 Redirect to my Login page (it is like the user isn't connected) instead of 200):

public class AddTest
    {
        private ILinkRepository _linkRepository;
        private ITempDataDictionary _temp;
        private WebApplicationFactory<Program> _factory;

        [OneTimeSetUp]
        public async Task SetUp()
        {
            _linkRepository = Substitute.For<ILinkRepository>();
            _temp = Substitute.For<ITempDataDictionary>();
            _factory = new WebApplicationFactory<Program>();
        }

        [Test]
        public async Task GivenPage_WhenDisplayingPage_ThenElementsAreDisplaying()
        {
            // Arrange
            var client = _factory.WithWebHostBuilder(builder =>
            {
                builder.ConfigureTestServices(services =>
                {
                    services.AddAuthentication(defaultScheme: "TestScheme")
                        .AddScheme<AuthenticationSchemeOptions, TestAuthHandler>(
                            "TestScheme", options => { });
                });
            })
                .CreateClient(new WebApplicationFactoryClientOptions
                {
                    AllowAutoRedirect = false,
                });

            client.DefaultRequestHeaders.Authorization =
                new AuthenticationHeaderValue(scheme: "TestScheme");

            //Act
            var response = await client.GetAsync("/admin/links/add");

            // Assert
            Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK));
        }
}

Here is the TestAuthHandler.cs:

public class TestAuthHandler : AuthenticationHandler<AuthenticationSchemeOptions>
    {
        public TestAuthHandler(IOptionsMonitor<AuthenticationSchemeOptions> options,
            ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock)
            : base(options, logger, encoder, clock)
        {
        }

        protected override Task<AuthenticateResult> HandleAuthenticateAsync()
        {
            var claims = new[] { 
                new Claim(ClaimTypes.Name, "Test user"),
                new Claim(ClaimTypes.Role, "Admin")
            };
            var identity = new ClaimsIdentity(claims, "Test");
            var principal = new ClaimsPrincipal(identity);
            var ticket = new AuthenticationTicket(principal, "TestScheme");

            var result = AuthenticateResult.Success(ticket);

            return Task.FromResult(result);
        }
    }

Here is my Program.cs:

var builder = WebApplication.CreateBuilder(args);

// Load environment variable
DotNetEnv.Env.Load();

// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddControllers();

builder.Services.AddDbContext<ASQuebecDbContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("ASQuebecDbConnectionString"))
);

builder.Services.AddDbContext<AuthDbContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("AuthenticationDbConnectionString"))
);

builder.Services.AddIdentity<IdentityUser, IdentityRole>()
    .AddEntityFrameworkStores<AuthDbContext>();

builder.Services.Configure<IdentityOptions>(options =>
{
    // Default setting password
    options.Password.RequireDigit = true;
    options.Password.RequireLowercase = true;
    options.Password.RequireNonAlphanumeric = true;
    options.Password.RequireUppercase = true;
    options.Password.RequiredLength = 6;
    options.Password.RequiredUniqueChars = 1;
});

builder.Services.ConfigureApplicationCookie(
    options =>
    {
        options.LoginPath = "/Login";
        options.AccessDeniedPath = "/AccessDenied";
    }  
);

builder.Services.AddScoped<ITextPostRepository, TextPostRepository>();
builder.Services.AddScoped<ILinkRepository, LinkRepository>();
builder.Services.AddScoped<IImageRepository, ImageRepositoryCloudinary>();
builder.Services.AddScoped<ITagRepository, TagRepository>();
builder.Services.AddScoped<ITagManagementRepository, TagManagementRepository>();
builder.Services.AddScoped<ITextPostLikeRepository, TextPostLikeRepository>();
builder.Services.AddScoped<ITextPostCommentRepository, TextPostCommentRepository>();
builder.Services.AddScoped<IUserRepository, UserRepository>();
builder.Services.AddScoped<IEmailManager, EmailManager>();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

app.MapRazorPages();
app.MapControllers();

app.Run();

public partial class Program { }
// </snippet_all>

I'm using AngleSharp and NUnit v. 3.13.3, so what should I do for accessing the page /admin/links/add in order to test the rendering and etc...

1

There are 1 best solutions below

0
mathdx On
        [Test]
        public async Task GivenPage_WhenDisplayingPage_ThenElementsAreDisplaying()
        {
            // Arrange
            var client = _factory.WithWebHostBuilder(builder =>
            {
                builder.ConfigureTestServices(services =>
                {
                    services.AddSingleton<TestAuthHandler>(); //HERE ADDED
                    services.AddAuthentication(options =>
                    {
                        options.DefaultAuthenticateScheme = "TestScheme";
                        options.DefaultChallengeScheme = "TestScheme";
                    }).AddScheme<AuthenticationSchemeOptions, TestAuthHandler>(
                        "TestScheme", options => { });

                    services.ConfigureApplicationCookie(options =>
                    {
                        options.Cookie.Name = ".AspNetCore.TestCookie";
                        options.LoginPath = "/Login";
                    }); //HERE ADDED
                });
            })
                .CreateClient(new WebApplicationFactoryClientOptions
                {
                    AllowAutoRedirect = false,
                });

            client.DefaultRequestHeaders.Authorization =
                new AuthenticationHeaderValue(scheme: "TestScheme");

            //Act
            var response = await client.GetAsync("/admin/links/add");
            var content = await HtmlHelpers.GetDocumentAsync(response);
            var title = content.QuerySelector("#title").TextContent;

            // Assert
            Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK));
            Assert.That(title, Is.EqualTo("Ajouter un lien"));
        }