Tech stack stub page and changing project to be just one Web Assembly project for now

This commit is contained in:
2026-05-27 11:25:04 -04:00
parent 8a20cfec4f
commit dd74f9b69f
140 changed files with 64156 additions and 97 deletions
+25
View File
@@ -0,0 +1,25 @@
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
namespace AOW4.SeleniumTests.Driver;
public static class DriverFactory
{
public static IWebDriver CreateChromeDriver()
{
var options = new ChromeOptions();
var headless = Environment.GetEnvironmentVariable("HEADLESS");
if (!string.IsNullOrEmpty(headless) &&
(headless == "1" || headless.Equals("true", StringComparison.OrdinalIgnoreCase)))
options.AddArgument("--headless=new");
options.AddArgument("--disable-gpu");
options.AddArgument("--no-sandbox");
options.AddArgument("--disable-dev-shm-usage");
var service = ChromeDriverService.CreateDefaultService();
service.HideCommandPromptWindow = true;
return new ChromeDriver(service, options);
}
}
+19
View File
@@ -0,0 +1,19 @@
using OpenQA.Selenium;
namespace AOW4.SeleniumTests.Pages;
public class CounterPage
{
private readonly IWebDriver _driver;
public CounterPage(IWebDriver driver)
{
_driver = driver;
}
public bool IsAt()
{
var url = _driver.Url ?? string.Empty;
return url.Contains("counter", StringComparison.OrdinalIgnoreCase) || _driver.PageSource.Contains("Counter");
}
}
+20
View File
@@ -0,0 +1,20 @@
using OpenQA.Selenium;
namespace AOW4.SeleniumTests.Pages;
public class HomePage
{
private readonly IWebDriver _driver;
public HomePage(IWebDriver driver)
{
_driver = driver;
}
public bool IsAt()
{
var url = _driver.Url ?? string.Empty;
return url.EndsWith("/") || url.Contains("/index", StringComparison.OrdinalIgnoreCase) ||
_driver.PageSource.Contains("Home");
}
}
+25
View File
@@ -0,0 +1,25 @@
using OpenQA.Selenium;
namespace AOW4.SeleniumTests.Pages;
public class NavMenuPage
{
private readonly IWebDriver _driver;
public NavMenuPage(IWebDriver driver)
{
_driver = driver;
}
public void ClickLinkByText(string linkText)
{
var link = _driver.FindElements(By.CssSelector("a[href]"))
.FirstOrDefault(e =>
!string.IsNullOrWhiteSpace(e.Text) &&
e.Text.Trim().Equals(linkText, StringComparison.OrdinalIgnoreCase));
if (link == null) throw new NoSuchElementException($"Link with text '{linkText}' not found in the page.");
link.Click();
}
}
+22
View File
@@ -0,0 +1,22 @@
# AOW4 Selenium Tests
Requirements:
- .NET 10 SDK
- Google Chrome installed (compatible with ChromeDriver package)
- The AOW4 web app running locally (by default at `http://localhost:5000`) or set `BASE_URL` env var.
Run tests:
```powershell
# optional: run headless
$env:HEADLESS = "1"
# optional: point to running app
$env:BASE_URL = "http://localhost:5000"
dotnet test AOW4.SeleniumTests\AOW4.SeleniumTests.csproj
```
Notes:
- Navigation tests use the UI nav links — ensure the app is running before executing tests.
- Broken links scanner sends HTTP HEAD requests and falls back to GET if needed.
+19
View File
@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<IsPackable>false</IsPackable>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<RootNamespace>AOW4.SeleniumTests</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Selenium.WebDriver" Version="4.44.0"/>
<PackageReference Include="Selenium.Support" Version="4.44.0"/>
<PackageReference Include="NUnit" Version="4.6.1"/>
<PackageReference Include="NUnit3TestAdapter" Version="6.2.0"/>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.5.1"/>
</ItemGroup>
</Project>
+36
View File
@@ -0,0 +1,36 @@
using AOW4.SeleniumTests.Driver;
using NUnit.Framework;
using OpenQA.Selenium;
namespace AOW4.SeleniumTests.Tests;
[TestFixture]
public abstract class BaseTest
{
[OneTimeSetUp]
public void GlobalSetup()
{
Driver = DriverFactory.CreateChromeDriver();
Driver.Manage().Window.Maximize();
}
[OneTimeTearDown]
public void GlobalTeardown()
{
try
{
Driver.Quit();
}
catch
{
}
}
protected IWebDriver Driver = null!;
protected string BaseUrl => "http://localhost:5212/";
protected void GoHome()
{
Driver.Navigate().GoToUrl(BaseUrl);
}
}
+62
View File
@@ -0,0 +1,62 @@
using NUnit.Framework;
using OpenQA.Selenium;
namespace AOW4.SeleniumTests.Tests;
[TestFixture]
public class BrokenLinksTest : BaseTest
{
[Test]
public void ScanAndReportBrokenLinks()
{
GoHome();
var anchors = Driver.FindElements(By.CssSelector("a[href]"))
.Select(a => a.GetAttribute("href") ?? string.Empty)
.Where(h => !string.IsNullOrWhiteSpace(h))
.Distinct()
.ToList();
var failures = new List<string>();
using var client = new HttpClient();
foreach (var raw in anchors)
{
if (raw.StartsWith("javascript:", StringComparison.OrdinalIgnoreCase))
continue;
if (raw.StartsWith("mailto:", StringComparison.OrdinalIgnoreCase))
continue;
Uri uri;
try
{
uri = new Uri(raw, UriKind.RelativeOrAbsolute);
if (!uri.IsAbsoluteUri) uri = new Uri(new Uri(BaseUrl), raw);
}
catch
{
failures.Add($"Invalid URI: {raw}");
continue;
}
try
{
using var req = new HttpRequestMessage(HttpMethod.Head, uri);
var resp = client.Send(req);
if (!resp.IsSuccessStatusCode)
{
// try GET as fallback
using var greq = new HttpRequestMessage(HttpMethod.Get, uri);
var gresp = client.Send(greq);
if (!gresp.IsSuccessStatusCode) failures.Add($"{(int)gresp.StatusCode} {uri}");
}
}
catch (Exception ex)
{
failures.Add($"Error checking {uri}: {ex.Message}");
}
}
if (failures.Any()) Assert.Fail("Broken links found:\n" + string.Join("\n", failures));
}
}
+18
View File
@@ -0,0 +1,18 @@
using NUnit.Framework;
namespace AOW4.SeleniumTests.Tests;
[TestFixture]
public class NavigationTests : BaseTest
{
[TestCase("Building Plan Calculator", "/building-calculator")]
public void ClickNavLink_NavigatesToPage(string linkText, string expectedPath)
{
GoHome();
Assert.IsTrue(
Driver.Url.Contains(expectedPath, StringComparison.OrdinalIgnoreCase) ||
Driver.PageSource.Contains(linkText),
$"Expected to be on route containing '{expectedPath}' after clicking '{linkText}', but was '{Driver.Url}'");
}
}