Replace custom socket implementation with SignalR.
Replace MSAL and custom cookie auth with Microsoft.Identity.EntityFramework Also some UI redesign to accommodate different login experience.
This commit is contained in:
114
Tests/AcceptanceTests/TestSetup/AatTestFixture.cs
Normal file
114
Tests/AcceptanceTests/TestSetup/AatTestFixture.cs
Normal file
@@ -0,0 +1,114 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using System.Net.Http.Json;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace Shogi.AcceptanceTests.TestSetup;
|
||||
|
||||
/// <summary>
|
||||
/// Acceptance Test fixture for tests which assert features for Microsoft accounts.
|
||||
/// </summary>
|
||||
public class AatTestFixture : IAsyncLifetime, IDisposable
|
||||
{
|
||||
protected static readonly JsonSerializerOptions SerializerOptions = new(JsonSerializerDefaults.Web);
|
||||
|
||||
private readonly string testAccountPassword;
|
||||
private bool disposedValue;
|
||||
|
||||
public AatTestFixture()
|
||||
{
|
||||
this.Configuration = new ConfigurationBuilder()
|
||||
.AddJsonFile("appsettings.json")
|
||||
.AddJsonFile("appsettings.Development.json", optional: true)
|
||||
.Build();
|
||||
|
||||
var baseUrl = this.Configuration["ServiceUrl"] ?? throw new InvalidOperationException();
|
||||
this.HttpClient = new HttpClient
|
||||
{
|
||||
BaseAddress = new Uri(baseUrl, UriKind.Absolute)
|
||||
};
|
||||
this.OtherHttpClient = new HttpClient
|
||||
{
|
||||
BaseAddress = new Uri(baseUrl, UriKind.Absolute)
|
||||
};
|
||||
|
||||
this.testAccountPassword = this.Configuration["TestUserPassword"]!;
|
||||
if (string.IsNullOrWhiteSpace(this.testAccountPassword))
|
||||
{
|
||||
throw new InvalidOperationException("TestUserPassword is not configured.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public IConfiguration Configuration { get; private set; }
|
||||
public HttpClient HttpClient { get; }
|
||||
public HttpClient OtherHttpClient { get; }
|
||||
|
||||
protected async Task LoginToTestAccounts()
|
||||
{
|
||||
var response = await this.HttpClient.PostAsJsonAsync(
|
||||
RelativeUri("login"),
|
||||
new
|
||||
{
|
||||
email = "aat-account",
|
||||
password = this.testAccountPassword,
|
||||
},
|
||||
options: SerializerOptions);
|
||||
|
||||
response.IsSuccessStatusCode.Should().BeTrue(because: "The test account should exist. If it does not, use the /Account/TestAccount route to create it.");
|
||||
|
||||
var bearerToken = (await response.Content.ReadFromJsonAsync<LoginResponse>())?.AccessToken;
|
||||
this.HttpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", bearerToken);
|
||||
|
||||
response = await this.HttpClient.PostAsJsonAsync(
|
||||
RelativeUri("login"),
|
||||
new
|
||||
{
|
||||
email = "aat-account-2",
|
||||
password = this.testAccountPassword,
|
||||
},
|
||||
options: SerializerOptions);
|
||||
|
||||
response.IsSuccessStatusCode.Should().BeTrue(because: "The test account should exist. If it does not, use the /Account/TestAccount route to create it.");
|
||||
|
||||
bearerToken = (await response.Content.ReadFromJsonAsync<LoginResponse>())?.AccessToken;
|
||||
this.OtherHttpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", bearerToken);
|
||||
}
|
||||
|
||||
public async Task InitializeAsync()
|
||||
{
|
||||
await this.LoginToTestAccounts();
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!this.disposedValue)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
this.HttpClient.Dispose();
|
||||
}
|
||||
|
||||
this.disposedValue = true;
|
||||
}
|
||||
}
|
||||
|
||||
public Task DisposeAsync()
|
||||
{
|
||||
this.Dispose(true);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
this.Dispose(disposing: true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected static Uri RelativeUri(string s) => new(s, UriKind.Relative);
|
||||
|
||||
private class LoginResponse
|
||||
{
|
||||
public string AccessToken { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace Shogi.AcceptanceTests.TestSetup;
|
||||
|
||||
/// <summary>
|
||||
/// Acceptance Test fixture for tests which assert features for Microsoft accounts.
|
||||
/// </summary>
|
||||
public class GuestTestFixture : IAsyncLifetime, IDisposable
|
||||
{
|
||||
private bool disposedValue;
|
||||
|
||||
public GuestTestFixture()
|
||||
{
|
||||
Configuration = new ConfigurationBuilder()
|
||||
.AddJsonFile("appsettings.json")
|
||||
.Build();
|
||||
|
||||
var baseUrl = Configuration["ServiceUrl"] ?? throw new InvalidOperationException("ServiceUrl configuration missing.");
|
||||
var baseAddress = new Uri(baseUrl, UriKind.Absolute);
|
||||
Guest1ServiceClient = new HttpClient
|
||||
{
|
||||
BaseAddress = baseAddress
|
||||
};
|
||||
Guest2ServiceClient = new HttpClient
|
||||
{
|
||||
BaseAddress = baseAddress
|
||||
};
|
||||
}
|
||||
|
||||
public IConfiguration Configuration { get; private set; }
|
||||
public HttpClient Guest2ServiceClient { get; }
|
||||
public HttpClient Guest1ServiceClient { get; }
|
||||
|
||||
public async Task InitializeAsync()
|
||||
{
|
||||
// Log in as some guest accounts and retain the session cookie for future requests.
|
||||
var guestLoginUri = new Uri("User/LoginAsGuest", UriKind.Relative);
|
||||
|
||||
var loginResponse = await Guest1ServiceClient.GetAsync(guestLoginUri);
|
||||
loginResponse.IsSuccessStatusCode.Should().BeTrue(because: "Guest accounts should work");
|
||||
var guestSessionCookie = loginResponse.Headers.GetValues("Set-Cookie").Single();
|
||||
Guest1ServiceClient.DefaultRequestHeaders.Add("Set-Cookie", guestSessionCookie);
|
||||
|
||||
loginResponse = await Guest2ServiceClient.GetAsync(guestLoginUri);
|
||||
loginResponse.IsSuccessStatusCode.Should().BeTrue(because: "Guest accounts should work twice");
|
||||
guestSessionCookie = loginResponse.Headers.GetValues("Set-Cookie").Single();
|
||||
Guest2ServiceClient.DefaultRequestHeaders.Add("Set-Cookie", guestSessionCookie);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!disposedValue)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
Guest1ServiceClient.Dispose();
|
||||
}
|
||||
|
||||
disposedValue = true;
|
||||
}
|
||||
}
|
||||
|
||||
public Task DisposeAsync()
|
||||
{
|
||||
Dispose(true);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(disposing: true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
@@ -1,100 +0,0 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Identity.Client;
|
||||
using System.Net.Http.Headers;
|
||||
|
||||
namespace Shogi.AcceptanceTests.TestSetup
|
||||
{
|
||||
/// <summary>
|
||||
/// Acceptance Test fixture for tests which assert features for Microsoft accounts.
|
||||
/// </summary>
|
||||
public class MsalTestFixture : IAsyncLifetime, IDisposable
|
||||
{
|
||||
private bool disposedValue;
|
||||
private readonly IConfidentialClientApplication app;
|
||||
|
||||
public MsalTestFixture()
|
||||
{
|
||||
Configuration = new ConfigurationBuilder()
|
||||
.AddJsonFile("appsettings.json")
|
||||
.AddEnvironmentVariables()
|
||||
.AddUserSecrets<MsalTestFixture>()
|
||||
.Build();
|
||||
|
||||
var azure = Configuration.GetSection("Auth");
|
||||
app = ConfidentialClientApplicationBuilder
|
||||
.Create(azure["ClientId"])
|
||||
.WithTenantId(azure["TenantId"])
|
||||
.WithClientSecret(azure["SecretValue"])
|
||||
.Build();
|
||||
|
||||
Service = new HttpClient
|
||||
{
|
||||
BaseAddress = new Uri(Configuration["ServiceUrl"], UriKind.Absolute)
|
||||
};
|
||||
|
||||
|
||||
publicApp = PublicClientApplicationBuilder
|
||||
.Create(azure["ClientId"])
|
||||
.WithTenantId("common")
|
||||
.Build();
|
||||
|
||||
}
|
||||
|
||||
public IConfiguration Configuration { get; private set; }
|
||||
|
||||
|
||||
public HttpClient Service { get; }
|
||||
|
||||
private IPublicClientApplication publicApp;
|
||||
|
||||
public async Task InitializeAsync()
|
||||
{
|
||||
var scopes = Configuration.GetSection("Auth:Scopes").Get<string[]>();
|
||||
var authResult = await app
|
||||
.AcquireTokenForClient(scopes)
|
||||
.ExecuteAsync();
|
||||
|
||||
authResult.Should().NotBeNull();
|
||||
authResult.AccessToken.Should().NotBeNullOrEmpty();
|
||||
|
||||
Service.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authResult.AccessToken);
|
||||
|
||||
var accounts = await publicApp.GetAccountsAsync();
|
||||
var password = new System.Security.SecureString();
|
||||
foreach (var c in "some password")
|
||||
{
|
||||
password.AppendChar(c);
|
||||
}
|
||||
var th = await publicApp
|
||||
.AcquireTokenByIntegratedWindowsAuth(scopes)
|
||||
.ExecuteAsync();
|
||||
//var thing = await publicApp.AcquireTokenByUsernamePassword(scopes, "Need to create a test email.", password)
|
||||
//.ExecuteAsync();
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!disposedValue)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
Service.Dispose();
|
||||
}
|
||||
|
||||
disposedValue = true;
|
||||
}
|
||||
}
|
||||
|
||||
public Task DisposeAsync()
|
||||
{
|
||||
Dispose(true);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(disposing: true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user