diff --git a/ProjectLighthouse.Tests.WebsiteTests/Extensions/WebDriverExtensions.cs b/ProjectLighthouse.Tests.WebsiteTests/Extensions/WebDriverExtensions.cs
new file mode 100644
index 00000000..0dcaf297
--- /dev/null
+++ b/ProjectLighthouse.Tests.WebsiteTests/Extensions/WebDriverExtensions.cs
@@ -0,0 +1,13 @@
+using System;
+using OpenQA.Selenium;
+
+namespace ProjectLighthouse.Tests.WebsiteTests.Extensions;
+
+public static class WebDriverExtensions
+{
+ private static Uri GetUri(this IWebDriver driver) => new(driver.Url);
+
+ public static string GetPath(this IWebDriver driver) => driver.GetUri().AbsolutePath;
+
+ public static string GetErrorMessage(this IWebDriver driver) => driver.FindElement(By.CssSelector("#error-message > p")).Text;
+}
\ No newline at end of file
diff --git a/ProjectLighthouse.Tests.WebsiteTests/Integration/AdminTests.cs b/ProjectLighthouse.Tests.WebsiteTests/Integration/AdminTests.cs
index 79d15561..7078c163 100644
--- a/ProjectLighthouse.Tests.WebsiteTests/Integration/AdminTests.cs
+++ b/ProjectLighthouse.Tests.WebsiteTests/Integration/AdminTests.cs
@@ -14,14 +14,15 @@ namespace ProjectLighthouse.Tests.WebsiteTests.Integration;
[Trait("Category", "Integration")]
public class AdminTests : LighthouseWebTest
{
- private const string adminPanelButtonXPath = "/html/body/div/header/div/div/div/a[2]";
+ private const string adminPanelButtonXPath = "/html/body/div/header/div/div/div/a[2]/span";
[Fact]
public async Task ShouldShowAdminPanelButtonWhenAdmin()
{
await using DatabaseContext database = await IntegrationHelper.GetIntegrationDatabase();
- Random random = new();
- UserEntity user = await database.CreateUser($"unitTestUser{random.Next()}", CryptoHelper.BCryptHash("i'm an engineering failure"));
+ this.Driver.Manage().Cookies.DeleteAllCookies();
+
+ UserEntity user = await database.CreateUser($"unitTestUser{CryptoHelper.GenerateRandomInt32()}", CryptoHelper.BCryptHash("i'm an engineering failure"));
WebTokenEntity webToken = new()
{
@@ -39,15 +40,16 @@ public class AdminTests : LighthouseWebTest
this.Driver.Manage().Cookies.AddCookie(new Cookie("LighthouseToken", webToken.UserToken));
this.Driver.Navigate().Refresh();
- Assert.Contains("Admin", this.Driver.FindElement(By.XPath(adminPanelButtonXPath)).Text);
+ Assert.Equal("Admin", this.Driver.FindElement(By.XPath(adminPanelButtonXPath)).Text);
}
[Fact]
public async Task ShouldNotShowAdminPanelButtonWhenNotAdmin()
{
await using DatabaseContext database = await IntegrationHelper.GetIntegrationDatabase();
- Random random = new();
- UserEntity user = await database.CreateUser($"unitTestUser{random.Next()}", CryptoHelper.BCryptHash("i'm an engineering failure"));
+ this.Driver.Manage().Cookies.DeleteAllCookies();
+
+ UserEntity user = await database.CreateUser($"unitTestUser{CryptoHelper.GenerateRandomInt32()}", CryptoHelper.BCryptHash("i'm an engineering failure"));
WebTokenEntity webToken = new()
{
@@ -65,6 +67,6 @@ public class AdminTests : LighthouseWebTest
this.Driver.Manage().Cookies.AddCookie(new Cookie("LighthouseToken", webToken.UserToken));
this.Driver.Navigate().Refresh();
- Assert.DoesNotContain("Admin", this.Driver.FindElement(By.XPath(adminPanelButtonXPath)).Text);
+ Assert.Empty(this.Driver.FindElements(By.XPath(adminPanelButtonXPath)));
}
}
\ No newline at end of file
diff --git a/ProjectLighthouse.Tests.WebsiteTests/Integration/AuthenticationTests.cs b/ProjectLighthouse.Tests.WebsiteTests/Integration/AuthenticationTests.cs
index f1d1f107..4151d9bc 100644
--- a/ProjectLighthouse.Tests.WebsiteTests/Integration/AuthenticationTests.cs
+++ b/ProjectLighthouse.Tests.WebsiteTests/Integration/AuthenticationTests.cs
@@ -3,11 +3,13 @@ using System.Linq;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Helpers;
+using LBPUnion.ProjectLighthouse.Localization.StringLists;
using LBPUnion.ProjectLighthouse.Tests.Helpers;
using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
using LBPUnion.ProjectLighthouse.Types.Entities.Token;
using Microsoft.EntityFrameworkCore;
using OpenQA.Selenium;
+using ProjectLighthouse.Tests.WebsiteTests.Extensions;
using Xunit;
namespace ProjectLighthouse.Tests.WebsiteTests.Integration;
@@ -19,10 +21,10 @@ public class AuthenticationTests : LighthouseWebTest
public async Task ShouldLoginWithPassword()
{
await using DatabaseContext database = await IntegrationHelper.GetIntegrationDatabase();
- Random random = new();
+ this.Driver.Manage().Cookies.DeleteAllCookies();
string password = CryptoHelper.Sha256Hash(CryptoHelper.GenerateRandomBytes(64).ToArray());
- UserEntity user = await database.CreateUser($"unitTestUser{random.Next()}", CryptoHelper.BCryptHash(CryptoHelper.Sha256Hash(password)));
+ UserEntity user = await database.CreateUser($"unitTestUser{CryptoHelper.GenerateRandomInt32()}", CryptoHelper.BCryptHash(CryptoHelper.Sha256Hash(password)));
this.Driver.Navigate().GoToUrl(this.BaseAddress + "/login");
@@ -33,16 +35,15 @@ public class AuthenticationTests : LighthouseWebTest
WebTokenEntity? webToken = await database.WebTokens.FirstOrDefaultAsync(t => t.UserId == user.UserId);
Assert.NotNull(webToken);
-
- await database.RemoveUser(user);
}
[Fact]
public async Task ShouldNotLoginWithNoPassword()
{
await using DatabaseContext database = await IntegrationHelper.GetIntegrationDatabase();
- Random random = new();
- UserEntity user = await database.CreateUser($"unitTestUser{random.Next()}", CryptoHelper.BCryptHash("just like the hindenberg,"));
+ this.Driver.Manage().Cookies.DeleteAllCookies();
+
+ UserEntity user = await database.CreateUser($"unitTestUser{CryptoHelper.GenerateRandomInt32()}", CryptoHelper.BCryptHash("just like the hindenberg,"));
this.Driver.Navigate().GoToUrl(this.BaseAddress + "/login");
@@ -53,15 +54,17 @@ public class AuthenticationTests : LighthouseWebTest
WebTokenEntity? webToken = await database.WebTokens.FirstOrDefaultAsync(t => t.UserId == user.UserId);
Assert.Null(webToken);
- await database.RemoveUser(user);
+ Assert.Equal("/login", this.Driver.GetPath());
+ Assert.Equal("The username or password you entered is invalid.", this.Driver.GetErrorMessage());
}
[Fact]
public async Task ShouldNotLoginWithWrongPassword()
{
await using DatabaseContext database = await IntegrationHelper.GetIntegrationDatabase();
- Random random = new();
- UserEntity user = await database.CreateUser($"unitTestUser{random.Next()}", CryptoHelper.BCryptHash("i'm an engineering failure"));
+ this.Driver.Manage().Cookies.DeleteAllCookies();
+
+ UserEntity user = await database.CreateUser($"unitTestUser{CryptoHelper.GenerateRandomInt32()}", CryptoHelper.BCryptHash("i'm an engineering failure"));
this.Driver.Navigate().GoToUrl(this.BaseAddress + "/login");
@@ -72,8 +75,6 @@ public class AuthenticationTests : LighthouseWebTest
WebTokenEntity? webToken = await database.WebTokens.FirstOrDefaultAsync(t => t.UserId == user.UserId);
Assert.Null(webToken);
-
- await database.RemoveUser(user);
}
[Fact]
@@ -82,8 +83,7 @@ public class AuthenticationTests : LighthouseWebTest
const string loggedInAsUsernameTextXPath = "/html/body/div/div/div/div/p[1]";
await using DatabaseContext database = await IntegrationHelper.GetIntegrationDatabase();
- Random random = new();
- UserEntity user = await database.CreateUser($"unitTestUser{random.Next()}", CryptoHelper.BCryptHash("i'm an engineering failure"));
+ UserEntity user = await database.CreateUser($"unitTestUser{CryptoHelper.GenerateRandomInt32()}", CryptoHelper.BCryptHash("i'm an engineering failure"));
WebTokenEntity webToken = new()
{
@@ -102,8 +102,7 @@ public class AuthenticationTests : LighthouseWebTest
Assert.DoesNotContain(user.Username, this.Driver.FindElement(By.XPath(loggedInAsUsernameTextXPath)).Text);
this.Driver.Manage().Cookies.AddCookie(new Cookie("LighthouseToken", webToken.UserToken));
navigation.Refresh();
- Assert.Contains(user.Username, this.Driver.FindElement(By.XPath(loggedInAsUsernameTextXPath)).Text);
- await database.RemoveUser(user);
+ Assert.Equal(Translate(LandingPageStrings.LoggedInAs, user.Username), this.Driver.FindElement(By.XPath(loggedInAsUsernameTextXPath)).Text);
}
}
\ No newline at end of file
diff --git a/ProjectLighthouse.Tests.WebsiteTests/Integration/LighthouseWebTest.cs b/ProjectLighthouse.Tests.WebsiteTests/Integration/LighthouseWebTest.cs
index 81698cf4..48b61077 100644
--- a/ProjectLighthouse.Tests.WebsiteTests/Integration/LighthouseWebTest.cs
+++ b/ProjectLighthouse.Tests.WebsiteTests/Integration/LighthouseWebTest.cs
@@ -1,6 +1,7 @@
using System;
using System.Linq;
using LBPUnion.ProjectLighthouse.Configuration;
+using LBPUnion.ProjectLighthouse.Localization;
using LBPUnion.ProjectLighthouse.Servers.Website.Startup;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Hosting.Server.Features;
@@ -21,6 +22,8 @@ public class LighthouseWebTest : IDisposable
protected LighthouseWebTest()
{
ServerConfiguration.Instance.DbConnectionString = "server=127.0.0.1;uid=root;pwd=lighthouse_tests;database=lighthouse_tests";
+ ServerConfiguration.Instance.TwoFactorConfiguration.TwoFactorEnabled = false;
+
this.webHost.Start();
IServerAddressesFeature? serverAddressesFeature = this.webHost.ServerFeatures.Get
();
@@ -38,8 +41,14 @@ public class LighthouseWebTest : IDisposable
}
this.Driver = new ChromeDriver(chromeOptions);
+ this.Driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(1);
}
+ protected static string Translate(TranslatableString translatableString) => translatableString.Translate(LocalizationManager.DefaultLang);
+
+ protected static string Translate(TranslatableString translatableString, params object?[] objects) =>
+ translatableString.Translate(LocalizationManager.DefaultLang, objects);
+
public void Dispose()
{
this.Driver.Close();
diff --git a/ProjectLighthouse.Tests.WebsiteTests/Integration/RegisterTests.cs b/ProjectLighthouse.Tests.WebsiteTests/Integration/RegisterTests.cs
index 5edc8e56..b1441bc2 100644
--- a/ProjectLighthouse.Tests.WebsiteTests/Integration/RegisterTests.cs
+++ b/ProjectLighthouse.Tests.WebsiteTests/Integration/RegisterTests.cs
@@ -3,10 +3,12 @@ using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Configuration;
using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Helpers;
+using LBPUnion.ProjectLighthouse.Localization.StringLists;
using LBPUnion.ProjectLighthouse.Tests.Helpers;
using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
using Microsoft.EntityFrameworkCore;
using OpenQA.Selenium;
+using ProjectLighthouse.Tests.WebsiteTests.Extensions;
using Xunit;
namespace ProjectLighthouse.Tests.WebsiteTests.Integration;
@@ -18,6 +20,7 @@ public class RegisterTests : LighthouseWebTest
public async Task ShouldRegister()
{
await using DatabaseContext database = await IntegrationHelper.GetIntegrationDatabase();
+ this.Driver.Manage().Cookies.DeleteAllCookies();
ServerConfiguration.Instance.Authentication.RegistrationEnabled = true;
@@ -38,7 +41,7 @@ public class RegisterTests : LighthouseWebTest
UserEntity? user = await database.Users.FirstOrDefaultAsync(u => u.Username == username);
Assert.NotNull(user);
- await database.RemoveUser(user);
+ Assert.Equal("/", this.Driver.GetPath());
ServerConfiguration.Instance.Authentication.RegistrationEnabled = false;
}
@@ -47,6 +50,7 @@ public class RegisterTests : LighthouseWebTest
public async Task ShouldNotRegisterWithMismatchingPasswords()
{
await using DatabaseContext database = await IntegrationHelper.GetIntegrationDatabase();
+ this.Driver.Manage().Cookies.DeleteAllCookies();
ServerConfiguration.Instance.Authentication.RegistrationEnabled = true;
@@ -67,6 +71,9 @@ public class RegisterTests : LighthouseWebTest
UserEntity? user = await database.Users.FirstOrDefaultAsync(u => u.Username == username);
Assert.Null(user);
+ Assert.Equal("/register", this.Driver.GetPath());
+ Assert.Equal(Translate(ErrorStrings.PasswordDoesntMatch), this.Driver.GetErrorMessage());
+
ServerConfiguration.Instance.Authentication.RegistrationEnabled = false;
}
@@ -74,6 +81,7 @@ public class RegisterTests : LighthouseWebTest
public async Task ShouldNotRegisterWithTakenUsername()
{
await using DatabaseContext database = await IntegrationHelper.GetIntegrationDatabase();
+ this.Driver.Manage().Cookies.DeleteAllCookies();
ServerConfiguration.Instance.Authentication.RegistrationEnabled = true;
@@ -95,7 +103,9 @@ public class RegisterTests : LighthouseWebTest
this.Driver.FindElement(By.Id("submit")).Click();
- Assert.Contains("The username you've chosen is already taken.", this.Driver.PageSource);
+ Assert.Equal("/register", this.Driver.GetPath());
+
+ Assert.Equal(Translate(ErrorStrings.UsernameTaken), this.Driver.GetErrorMessage());
ServerConfiguration.Instance.Authentication.RegistrationEnabled = false;
}
diff --git a/ProjectLighthouse.Tests.WebsiteTests/ProjectLighthouse.Tests.WebsiteTests.csproj b/ProjectLighthouse.Tests.WebsiteTests/ProjectLighthouse.Tests.WebsiteTests.csproj
index 3e1a3e0f..d38e93e8 100644
--- a/ProjectLighthouse.Tests.WebsiteTests/ProjectLighthouse.Tests.WebsiteTests.csproj
+++ b/ProjectLighthouse.Tests.WebsiteTests/ProjectLighthouse.Tests.WebsiteTests.csproj
@@ -32,6 +32,7 @@
+
diff --git a/ProjectLighthouse/Helpers/CryptoHelper.cs b/ProjectLighthouse/Helpers/CryptoHelper.cs
index 068e9eb6..cfa896a2 100644
--- a/ProjectLighthouse/Helpers/CryptoHelper.cs
+++ b/ProjectLighthouse/Helpers/CryptoHelper.cs
@@ -60,6 +60,12 @@ public static class CryptoHelper
/// The randomly generated integer
public static int GenerateRandomInt32(int fromInclusive, int toExclusive) => RandomNumberGenerator.GetInt32(fromInclusive, toExclusive);
+ ///
+ /// Generates a random 32 bit integer between 0 and 2^32 - 1
+ ///
+ /// The randomly generated integer
+ public static int GenerateRandomInt32() => RandomNumberGenerator.GetInt32(0, int.MaxValue);
+
public static string ToBase64(string str)
{
byte[] bytes = Encoding.UTF8.GetBytes(str);