Skip to content

Commit

Permalink
Merge pull request #777 from pieterh/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
pieterh authored Apr 10, 2023
2 parents 97487f7 + d17123b commit 1cfcb29
Show file tree
Hide file tree
Showing 54 changed files with 185 additions and 80 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ jobs:
path: ${{ runner.temp }}/ems.zip
- name: Publish - Blazor WASM frontend
run: |
dotnet publish --no-restore --configuration Release --output publish/ems.blazorwasm frontend/EMS.BlazorWasm/EMS.BlazerWasm
dotnet publish --no-restore --configuration Release --output publish/ems.blazorwasm frontend/EMS.BlazorWasm/EMS.BlazorWasm
- name: Zip Release - Blazor WASM frontend
uses: TheDoctor0/zip-release@0.7.1
with:
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ Get the latest image from the repository:
docker pull pieterhil/energy-management-system:latest
```

Remove any old containers from the system that where left over from a prvious run.
Remove any old containers from the system that where left over from a previous run.
```
docker container rm hems
```
Expand All @@ -113,7 +113,7 @@ docker run \
-e EMS_PATHS_CONFIG=/app/ems/userdata/config.json \
-e EMS_PATHS_NLOG=/app/ems/userdata/NLog.config \
--name=hems \
pieterhil/energy-management-system:feature-blazorwasm
pieterhil/energy-management-system:latest
```

### Frontend
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="FluentAssertions" Version="6.10.0" />
<PackageReference Include="HtmlAgilityPack" Version="1.11.46" />
</ItemGroup>
<ItemGroup>
<None Remove="System.Text.RegularExpressions" />
Expand Down
32 changes: 32 additions & 0 deletions backend/EMS.WebHost.Integration.Tests/HttpClientExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System;
using System.Diagnostics.CodeAnalysis;
using Microsoft.VisualStudio.TestPlatform.CommunicationUtilities;

namespace EMS.WebHost.Integration.Tests
{
public static class HttpClientExtensions
{
public static Task<HttpResponseMessage> OptionsAsync(this HttpClient client, [StringSyntax(StringSyntaxAttribute.Uri)] string? requestUri) =>
OptionsAsync(client, CreateUri(requestUri));
public static Task<HttpResponseMessage> OptionsAsync(this HttpClient client, Uri? requestUri) =>
OptionsAsync(client, requestUri, CancellationToken.None);
public static Task<HttpResponseMessage> OptionsAsync(this HttpClient client, [StringSyntax(StringSyntaxAttribute.Uri)] string? requestUri, CancellationToken cancellationToken) =>
OptionsAsync(client, CreateUri(requestUri), cancellationToken);

[SuppressMessage("", "CA2000")]
[SuppressMessage("", "CA1062")]
public static Task<HttpResponseMessage> OptionsAsync(this HttpClient client, Uri? requestUri, CancellationToken cancellationToken)
{
HttpRequestMessage request = CreateRequestMessage(HttpMethod.Options, requestUri);
return client.SendAsync(request, cancellationToken);
}

#region Private Helpers
private static Uri? CreateUri(string? uri) =>
string.IsNullOrEmpty(uri) ? null : new Uri(uri, UriKind.RelativeOrAbsolute);
private static HttpRequestMessage CreateRequestMessage(HttpMethod method, Uri? uri) =>
new HttpRequestMessage(method, uri) { };
#endregion Private Helpers
}
}

23 changes: 15 additions & 8 deletions backend/EMS.WebHost.Integration.Tests/HttpTools.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,38 +5,43 @@

namespace EMS.WebHost.Integration.Tests
{
public enum Methods { POST, PUT, DELETE }
public enum Methods { POST, PUT, DELETE, GET }
internal static class HttpTools
{
{
#if DEBUG

private const string _dashes = "----------------------------";
[SuppressMessage("", "CA1303")]
#endif

public static async Task<bool> MethodNotAllowed(Uri baseUri, Methods method, string path)
public static async Task<bool> MethodNotAllowed(Uri baseUri, string relativeUrl, Methods method, string path)
{
HttpResponseMessage response;
using var _client = new HttpClient() { BaseAddress = new Uri("http://localhost:5005") };
using var _client = new HttpClient() { BaseAddress = baseUri };
switch (method)
{
case Methods.POST:
{
var model = new LoginModel() { Username = "a", Password = "b" };
using var content = JsonContent.Create<LoginModel>(model);
response = await _client.PostAsync(new Uri(_client.BaseAddress, "api/users/ping"), content).ConfigureAwait(true);
response = await _client.PostAsync(new Uri(_client.BaseAddress, relativeUrl), content).ConfigureAwait(true);
}
break;
case Methods.PUT:
{
var model = new LoginModel() { Username = "a", Password = "b" };
using var content = JsonContent.Create<LoginModel>(model);
response = await _client.PutAsync(new Uri(_client.BaseAddress, "api/users/ping"), content).ConfigureAwait(true);
response = await _client.PutAsync(new Uri(_client.BaseAddress, relativeUrl), content).ConfigureAwait(true);
}
break;
case Methods.DELETE:
{
response = await _client.DeleteAsync(new Uri(_client.BaseAddress, "api/users/ping")).ConfigureAwait(true);
response = await _client.DeleteAsync(new Uri(_client.BaseAddress, relativeUrl)).ConfigureAwait(true);
}
break;
case Methods.GET:
{
response = await _client.GetAsync(new Uri(_client.BaseAddress, relativeUrl)).ConfigureAwait(true);
}
break;
default:
Expand All @@ -50,6 +55,8 @@ public static async Task<bool> MethodNotAllowed(Uri baseUri, Methods method, str
#endif
return response.StatusCode == System.Net.HttpStatusCode.MethodNotAllowed;
}


}
}

188 changes: 129 additions & 59 deletions backend/EMS.WebHost.Integration.Tests/UnitTest1.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,82 +3,152 @@
using System.Text.Json;
using System.Threading;
using EMS.WebHost.Controllers;
using HtmlAgilityPack;
using Newtonsoft.Json.Linq;

namespace EMS.WebHost.Integration.Tests;

public class UsersController
namespace EMS.WebHost.Integration.Tests
{
public class UsersController
{
const string BASE_ADDRESS = "http://localhost:5005";

#if DEBUG
private readonly string _dashes;
private readonly string _dashes;
#endif
private readonly Uri _baseAddress;
private readonly Uri _baseAddress;

public UsersController() {
public UsersController()
{
#if DEBUG
_dashes = "----------------------------";
_dashes = "----------------------------";
#endif
_baseAddress = new Uri("http://localhost:5005");
}
_baseAddress = new Uri(BASE_ADDRESS);
}

[Theory(DisplayName = "Ping - is method allowed")]
[InlineData(Methods.POST, true)]
[InlineData(Methods.PUT, true)]
[InlineData(Methods.DELETE, true)]
public async Task Test3(Methods method, bool methodNotAllowed)
{
Assert.Equal(methodNotAllowed, await HttpTools.MethodNotAllowed(_baseAddress, method, "api/users/ping").ConfigureAwait(true));
}
[Theory(DisplayName = "Ping - is method allowed")]
[InlineData(Methods.POST, true)]
[InlineData(Methods.PUT, true)]
[InlineData(Methods.DELETE, true)]
public async Task Test1(Methods method, bool methodNotAllowed)
{
Assert.Equal(methodNotAllowed, await HttpTools.MethodNotAllowed(_baseAddress, "api/users/ping", method, "api/users/ping").ConfigureAwait(true));
}

[Fact(DisplayName = "Ping - Should give 401 when not authenticated,")]
public async Task Test1()
{
using var _client = new HttpClient() { BaseAddress = _baseAddress };
var response = await _client.GetAsync(new Uri(_client.BaseAddress, "api/users/ping")).ConfigureAwait(true);
# if DEBUG
Console.WriteLine(_dashes);
Console.WriteLine(response.StatusCode);
Console.WriteLine(response.ToString());
[Fact(DisplayName = "Ping - Should give 401 when not authenticated,")]
public async Task Test2()
{
using var _client = new HttpClient() { BaseAddress = _baseAddress };
var response = await _client.GetAsync(new Uri(_client.BaseAddress, "api/users/ping")).ConfigureAwait(true);
#if DEBUG
Console.WriteLine(_dashes);
Console.WriteLine(response.StatusCode);
Console.WriteLine(response.ToString());
#endif
Assert.Equal(System.Net.HttpStatusCode.Unauthorized, response.StatusCode);
}
Assert.Equal(System.Net.HttpStatusCode.Unauthorized, response.StatusCode);
}

[Fact(DisplayName = "Authenticate - Should give an error when credentials are invalid")]
public async Task Test5()
{
using var _client = new HttpClient() { BaseAddress = new Uri("http://localhost:5005") };
var model = new LoginModel() { Username = "a", Password = "b" };
using var content = JsonContent.Create<LoginModel>(model);
var response = await _client.PostAsync(new Uri(_client.BaseAddress, "api/users/authenticate"), content).ConfigureAwait(true);
[Fact(DisplayName = "Authenticate - Should give an error when credentials are invalid")]
public async Task Test5()
{
using var _client = new HttpClient() { BaseAddress = new Uri("http://localhost:5005") };
var model = new LoginModel() { Username = "a", Password = "b" };
using var content = JsonContent.Create<LoginModel>(model);
var response = await _client.PostAsync(new Uri(_client.BaseAddress, "api/users/authenticate"), content).ConfigureAwait(true);
#if DEBUG
Console.WriteLine(_dashes);
Console.WriteLine(response.StatusCode);
Console.WriteLine(response.ToString());
#endif
Assert.False(response.IsSuccessStatusCode);
Assert.Equal(System.Net.HttpStatusCode.Unauthorized, response.StatusCode);
}

[Fact(DisplayName = "Authenticate - Should give a token when credentials are valid")]
public async Task Test6()
{
using var _client = new HttpClient() { BaseAddress = new Uri("http://localhost:5005") };
var model = new LoginModel() { Username = "admin", Password = "admin" };
using var content = JsonContent.Create<LoginModel>(model);
var response = await _client.PostAsync(new Uri(_client.BaseAddress, "api/users/authenticate"), content).ConfigureAwait(true);
#if DEBUG
Console.WriteLine(_dashes);
Console.WriteLine(response.StatusCode);
Console.WriteLine(response.ToString());
Console.WriteLine(_dashes);
Console.WriteLine(response.StatusCode);
Console.WriteLine(response.ToString());
#endif
Assert.False(response.IsSuccessStatusCode);
Assert.Equal(System.Net.HttpStatusCode.Unauthorized, response.StatusCode);
Assert.True(response.IsSuccessStatusCode);
Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode);

var loginResponse = await response.Content.ReadFromJsonAsync<LoginResponse>(new JsonSerializerOptions { PropertyNameCaseInsensitive = true }).ConfigureAwait(true);
Assert.False(string.IsNullOrWhiteSpace(loginResponse?.User.Id.ToString()));
Assert.False(string.IsNullOrWhiteSpace(loginResponse?.User.Name));
Assert.False(string.IsNullOrWhiteSpace(loginResponse?.User.Username));
Assert.False(string.IsNullOrWhiteSpace(loginResponse?.Token));
Assert.Equal(200, loginResponse?.Status);
}
}

[Fact(DisplayName = "Authenticate - Should give a token when credentials are valid")]
public async Task Test6()
public class BlazorWasm
{
using var _client = new HttpClient() { BaseAddress = new Uri("http://localhost:5005") };
var model = new LoginModel() { Username = "admin", Password = "admin" };
using var content = JsonContent.Create<LoginModel>(model);
var response = await _client.PostAsync(new Uri(_client.BaseAddress, "api/users/authenticate"), content).ConfigureAwait(true);
const string BASE_ADDRESS = "http://localhost:5005";
private readonly Uri _baseAddress;

public BlazorWasm()
{
_baseAddress = new Uri(BASE_ADDRESS);
}

[Fact(DisplayName = "BlazorWasm - should return the title page as the home page")]
public async Task Test1()
{
using var _client = new HttpClient() { BaseAddress = _baseAddress };
using var response = await _client.GetAsync(new Uri(_client.BaseAddress, "")).ConfigureAwait(true);

Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode);
var t = new System.Net.Http.Headers.MediaTypeHeaderValue("text/html");
Assert.Equal(t, response.Content.Headers.ContentType);
var content = await response.Content.ReadAsStringAsync().ConfigureAwait(true);
content.Contains("<title>EMS.BlazorWasm</title>", StringComparison.OrdinalIgnoreCase);
content.Should().Contain("<title>EMS.BlazorWasm</title>");
}

[Fact(DisplayName = "BlazorWasm - should be able to load the referenced files")]
public async Task Test2()
{
using var _client = new HttpClient() { BaseAddress = _baseAddress };
using var response = await _client.GetAsync(new Uri(_client.BaseAddress, "")).ConfigureAwait(true);

Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode);
var t = new System.Net.Http.Headers.MediaTypeHeaderValue("text/html");
Assert.Equal(t, response.Content.Headers.ContentType);
var html = await response.Content.ReadAsStringAsync().ConfigureAwait(true);

HtmlDocument htmlSnippet = new HtmlDocument();
htmlSnippet.LoadHtml(html);

foreach (HtmlNode link in htmlSnippet.DocumentNode.SelectNodes("//link[@href]|//script[@src]"))
{
HtmlAttribute attHref = link.Attributes["href"];
HtmlAttribute attSrc = link.Attributes["src"];
string? url = attHref?.Value ?? attSrc?.Value;

if (url != null && !url.StartsWith("http", StringComparison.OrdinalIgnoreCase))
{
#if DEBUG
Console.WriteLine(_dashes);
Console.WriteLine(response.StatusCode);
Console.WriteLine(response.ToString());
Console.WriteLine($"Validating -> {url} ");
#endif
Assert.True(response.IsSuccessStatusCode);
Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode);

var loginResponse = await response.Content.ReadFromJsonAsync<LoginResponse>(new JsonSerializerOptions { PropertyNameCaseInsensitive = true }).ConfigureAwait(true);
Assert.False(string.IsNullOrWhiteSpace(loginResponse?.User.Id.ToString()));
Assert.False(string.IsNullOrWhiteSpace(loginResponse?.User.Name));
Assert.False(string.IsNullOrWhiteSpace(loginResponse?.User.Username));
Assert.False(string.IsNullOrWhiteSpace(loginResponse?.Token));
Assert.Equal(200, loginResponse?.Status);
using var response2 = await _client.GetAsync(new Uri(_client.BaseAddress, url)).ConfigureAwait(true);

response2.StatusCode.Should().Be(System.Net.HttpStatusCode.OK, "we expect to be able to download file {0}", url);
_ = await response2.Content.ReadAsStringAsync().ConfigureAwait(true);
}
#if DEBUG
else
{
Console.WriteLine($"Not validating -> {url} ");
}
#endif
}

}
}
}
}
1 change: 1 addition & 0 deletions backend/EMS.WebHost.Integration.Tests/Usings.cs
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
global using Xunit;
global using FluentAssertions;
8 changes: 2 additions & 6 deletions backend/EMS.WebHost/Controllers/UsersController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,23 +42,19 @@ public class UserModel
public Guid Id { get; set; }
public required string Username { get; init; }
public required string Name { get; init; }
}


}

[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
[ApiController]
[Route("api/[controller]")]
public class UsersController : ControllerBase
{
private ILogger Logger { get; init; }
private readonly IWebHostEnvironment _env;
private readonly IJwtService _jwtService;

public UsersController(ILogger<UsersController> logger, IWebHostEnvironment env, IJwtService jwtService)
public UsersController(ILogger<UsersController> logger, IJwtService jwtService)
{
Logger = logger;
_env = env;
_jwtService = jwtService;
}

Expand Down
3 changes: 0 additions & 3 deletions backend/EMS.WebHost/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,6 @@ public void Configure(ILogger<Startup> logger, IApplicationBuilder app)
app.UseMiddleware<Middleware.SecurityHeaders>();
app.UseDefaultFiles();
app.UseResponseCompression();
//app.UseStaticFiles();

var provider = new FileExtensionContentTypeProvider();
provider.Mappings.Clear();
Expand Down Expand Up @@ -202,8 +201,6 @@ public void Configure(ILogger<Startup> logger, IApplicationBuilder app)
ServeUnknownFileTypes = true
});

//app.UseMiddleware<Middleware.SpaMiddleware>(Logger);

app.UseRouting();

app.UseCors(MyAllowSpecificOrigins);
Expand Down
2 changes: 1 addition & 1 deletion frontend/EMS.BlazorWasm/EMS.BlazorWasm.sln
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 25.0.1704.4
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EMS.BlazorWasm", "EMS.BlazerWasm\EMS.BlazorWasm.csproj", "{5882ADE4-12CD-497B-AA0C-3A7B3DB1301F}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EMS.BlazorWasm", "EMS.BlazorWasm\EMS.BlazorWasm.csproj", "{5882ADE4-12CD-497B-AA0C-3A7B3DB1301F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down

0 comments on commit 1cfcb29

Please sign in to comment.