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

feat: Pin/unpin, UX- and E2E testing improvements #50

Merged
merged 12 commits into from
Apr 1, 2024
Merged
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,11 @@ dotnet ef migrations add Initial
dotnet ef database update
```

## E2E Testing

E2E testing is done via [Playwright](https://playwright.dev/dotnet/docs/writing-tests). The test suite automatically
spawns the test server and shuts it down after all tests are completed.

## Technology

- **Backend**: ASP.NET Core Web API
Expand Down
46 changes: 36 additions & 10 deletions src/Chrono.Tests/E2E/00_E2ETestBase.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
using Microsoft.Extensions.Configuration;
using Chrono.Shared.Services;
using Chrono.Tests.Helper;
using Microsoft.AspNetCore.Authorization.Policy;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Playwright;
using Microsoft.Playwright.NUnit;
using NUnit.Framework;
Expand All @@ -12,6 +18,7 @@ public partial class E2ETests : PlaywrightTest
private static readonly string[] PlaywrightArgs = ["install"];
private IBrowser _browser;
private IConfiguration _config;
private IHost _host;
private IPage _page;

[OneTimeSetUp]
Expand All @@ -23,14 +30,33 @@ public async Task Init()
.AddJsonFile("config.Local.json", true)
.Build();

_host = BuildTestApp();

await _host.StartAsync();

await InitPlaywright();
await Login_User();
}

private WebApplication BuildTestApp()
{
Environment.SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", "Development");
Environment.SetEnvironmentVariable("ASPNETCORE_HOSTINGSTARTUPASSEMBLIES", "Microsoft.AspNetCore.SpaProxy");
Environment.SetEnvironmentVariable("ConnectionStrings:DefaultConnection",
$"Data Source={_config["DatabaseFullPath"]}");

var builder = Program.CreateBuilder([$"urls={_config["BackendUrl"]!}"]);

// Disables Authentication for E2E tests (= no 2FA etc.)
builder.Services.AddScoped<ICurrentUserService, FakeCurrentUserService>();
builder.Services.AddSingleton<IPolicyEvaluator, FakePolicyEvaluator>();

return Program.BuildApp(builder);
}

private async Task InitPlaywright()
{
// Ensure the required web driver is installed.
Program.Main(PlaywrightArgs);
Microsoft.Playwright.Program.Main(PlaywrightArgs);

await PlaywrightSetup();

Expand All @@ -44,13 +70,13 @@ private async Task InitPlaywright()
});
}

private async Task Login_User()
[OneTimeTearDown]
public async Task TearDownWebApplication()
{
await _page.GotoAsync(_config["WebAppUrl"]!);
await _page.Locator("text=Login").ClickAsync();

await _page.GetByLabel("Email address").FillAsync(_config["TestUser:Username"]!);
await _page.GetByLabel("Password").FillAsync(_config["TestUser:Password"]!);
await _page.GetByRole(AriaRole.Button, new PageGetByRoleOptions { Name = "Continue" }).ClickAsync();
if (_host is not null)
{
await _host.StopAsync();
_host.Dispose();
}
}
}
10 changes: 10 additions & 0 deletions src/Chrono.Tests/Helper/FakeCurrentUserService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using Chrono.Shared.Services;

namespace Chrono.Tests.Helper;

public class FakeCurrentUserService : ICurrentUserService
{
public string UserId => "Testing";
public string UserName => "Testing";
public bool IsAuthenticated => true;
}
25 changes: 25 additions & 0 deletions src/Chrono.Tests/Helper/FakePolicyEvaluator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using System.Security.Claims;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Authorization.Policy;
using Microsoft.AspNetCore.Http;

namespace Chrono.Tests.Helper;

public class FakePolicyEvaluator : IPolicyEvaluator
{
public virtual async Task<AuthenticateResult> AuthenticateAsync(AuthorizationPolicy policy, HttpContext context)
{
var principal = new ClaimsPrincipal();
principal.AddIdentity(new ClaimsIdentity(Array.Empty<Claim>(), "FakeScheme"));

return await Task.FromResult(AuthenticateResult.Success(new AuthenticationTicket(principal,
new AuthenticationProperties(), "FakeScheme")));
}

public virtual async Task<PolicyAuthorizationResult> AuthorizeAsync(AuthorizationPolicy policy,
AuthenticateResult authenticationResult, HttpContext context, object resource)
{
return await Task.FromResult(PolicyAuthorizationResult.Success());
}
}
8 changes: 3 additions & 5 deletions src/Chrono.Tests/config.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
{
"WebAppUrl": "https://localhost:7151",
"BackendUrl": "https://localhost:7151",
"WebAppUrl": "https://localhost:44463",
"DatabaseFullPath": "/home/.../.../.../data/chrono_test.db",
"Options": {
"Headless": false,
"IgnoreHTTPSErrors": true
},
"TestUser": {
"Username": "<TODO>",
"Password": "<TODO>"
}
}
8 changes: 6 additions & 2 deletions src/Chrono/Chrono.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,18 @@
<None Include="$(SpaRoot)**" Exclude="$(SpaRoot)node_modules\**"/>
</ItemGroup>

<!-- Make internals visible to Chrono.Tests -->
<ItemGroup>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
<_Parameter1>$(MSBuildProjectName).Tests</_Parameter1>
</AssemblyAttribute>
</ItemGroup>

<ItemGroup>
<_ContentIncludedByDefault Remove="Pages\Error.cshtml"/>
<_ContentIncludedByDefault Remove="Pages\_ViewImports.cshtml"/>

</ItemGroup>


<Target Name="DebugEnsureNodeEnv" BeforeTargets="Build" Condition=" '$(Configuration)' == 'Debug' And !Exists('$(SpaRoot)node_modules') ">
<!-- Ensure Node.js is installed -->
<Exec Command="node --version" ContinueOnError="true">
Expand Down
Loading
Loading