Replace Playwright smoke tests with Selenium
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
param(
|
||||
[switch]$SkipDotnetRestore,
|
||||
[switch]$SkipBuild,
|
||||
[switch]$SkipBrowserSmoke,
|
||||
[switch]$SkipPlaywright
|
||||
)
|
||||
|
||||
@@ -66,10 +67,6 @@ try {
|
||||
npm ci
|
||||
}
|
||||
|
||||
Invoke-Step -Name "Ensure Playwright browser" -Action {
|
||||
npm exec playwright install chromium
|
||||
}
|
||||
|
||||
Invoke-Step -Name "Run tests" -Action {
|
||||
if ($SkipBuild) {
|
||||
dotnet test RpgRoller.Tests/RpgRoller.Tests.csproj --verbosity minimal --collect:"XPlat Code Coverage" --settings RpgRoller.Tests/coverlet.runsettings --results-directory $testResultsRoot
|
||||
@@ -83,9 +80,9 @@ try {
|
||||
pwsh ./scripts/check-coverage.ps1 -MinLineRate 0.90 -MinBranchRate 0.70 -ResultsRoot $testResultsRoot
|
||||
}
|
||||
|
||||
if (-not $SkipPlaywright) {
|
||||
Invoke-Step -Name "Run Playwright smoke test" -Action {
|
||||
pwsh ./scripts/run-playwright.ps1
|
||||
if (-not ($SkipBrowserSmoke -or $SkipPlaywright)) {
|
||||
Invoke-Step -Name "Run Selenium smoke test" -Action {
|
||||
node ./scripts/run-selenium.js
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
param(
|
||||
[string]$BaseUrl = "http://127.0.0.1:5095",
|
||||
[string]$Spec = "tests/e2e/smoke.spec.js"
|
||||
)
|
||||
|
||||
Set-StrictMode -Version Latest
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||
$repoRoot = Split-Path -Parent $scriptDir
|
||||
$appUrl = [Uri]$BaseUrl
|
||||
$healthUrl = "$BaseUrl/api/health"
|
||||
$tempDbPath = Join-Path $env:TEMP ("rpgroller-playwright-{0}.db" -f [Guid]::NewGuid().ToString("N"))
|
||||
$process = $null
|
||||
|
||||
Push-Location $repoRoot
|
||||
try {
|
||||
$env:ConnectionStrings__RpgRoller = "Data Source=$tempDbPath"
|
||||
$env:PLAYWRIGHT_BASE_URL = $BaseUrl
|
||||
|
||||
$process = Start-Process dotnet -ArgumentList @(
|
||||
"run",
|
||||
"--project",
|
||||
"RpgRoller/RpgRoller.csproj",
|
||||
"--verbosity"
|
||||
"minimal"
|
||||
"--urls",
|
||||
$BaseUrl
|
||||
) -WorkingDirectory $repoRoot -PassThru -NoNewWindow
|
||||
|
||||
$response = $null
|
||||
for ($i = 0; $i -lt 60; $i++) {
|
||||
try {
|
||||
$response = Invoke-WebRequest -Uri $healthUrl -UseBasicParsing -TimeoutSec 2
|
||||
if ($response.StatusCode -eq 200) {
|
||||
break
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Start-Sleep -Milliseconds 500
|
||||
}
|
||||
|
||||
Start-Sleep -Milliseconds 500
|
||||
}
|
||||
|
||||
if (-not $response -or $response.StatusCode -ne 200) {
|
||||
throw "Application failed to start on $BaseUrl."
|
||||
}
|
||||
|
||||
npm exec playwright test $Spec -- --reporter=line
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "Playwright exited with code $LASTEXITCODE."
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if ($process -and -not $process.HasExited) {
|
||||
Stop-Process -Id $process.Id -Force
|
||||
}
|
||||
|
||||
Remove-Item Env:\ConnectionStrings__RpgRoller -ErrorAction SilentlyContinue
|
||||
Remove-Item Env:\PLAYWRIGHT_BASE_URL -ErrorAction SilentlyContinue
|
||||
Pop-Location
|
||||
}
|
||||
90
scripts/run-selenium.js
Normal file
90
scripts/run-selenium.js
Normal file
@@ -0,0 +1,90 @@
|
||||
const fs = require("node:fs");
|
||||
const os = require("node:os");
|
||||
const path = require("node:path");
|
||||
const { spawn } = require("node:child_process");
|
||||
|
||||
const repoRoot = path.resolve(__dirname, "..");
|
||||
const baseUrl = process.env.SELENIUM_BASE_URL || "http://127.0.0.1:5095";
|
||||
const healthUrl = new URL("/api/health", baseUrl).toString();
|
||||
const smokeScript = process.argv[2] || "tests/e2e/smoke.js";
|
||||
const tempDbPath = path.join(os.tmpdir(), `rpgroller-selenium-${Date.now()}-${Math.random().toString(16).slice(2)}.db`);
|
||||
|
||||
function delay(ms) {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
async function waitForHealthCheck() {
|
||||
for (let attempt = 0; attempt < 60; attempt += 1) {
|
||||
try {
|
||||
const response = await fetch(healthUrl);
|
||||
if (response.ok) {
|
||||
return;
|
||||
}
|
||||
} catch {
|
||||
}
|
||||
|
||||
await delay(500);
|
||||
}
|
||||
|
||||
throw new Error(`Application failed to start on ${baseUrl}.`);
|
||||
}
|
||||
|
||||
function spawnProcess(command, args, options) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const child = spawn(command, args, options);
|
||||
child.once("error", reject);
|
||||
resolve(child);
|
||||
});
|
||||
}
|
||||
|
||||
async function run() {
|
||||
const app = await spawnProcess(
|
||||
"dotnet",
|
||||
["run", "--project", "RpgRoller/RpgRoller.csproj", "--verbosity", "minimal", "--urls", baseUrl],
|
||||
{
|
||||
cwd: repoRoot,
|
||||
stdio: "inherit",
|
||||
env: {
|
||||
...process.env,
|
||||
ConnectionStrings__RpgRoller: `Data Source=${tempDbPath}`
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
try {
|
||||
await waitForHealthCheck();
|
||||
|
||||
const smoke = await spawnProcess("node", [smokeScript], {
|
||||
cwd: repoRoot,
|
||||
stdio: "inherit",
|
||||
env: {
|
||||
...process.env,
|
||||
SELENIUM_BASE_URL: baseUrl
|
||||
}
|
||||
});
|
||||
|
||||
const exitCode = await new Promise((resolve, reject) => {
|
||||
smoke.once("error", reject);
|
||||
smoke.once("exit", resolve);
|
||||
});
|
||||
|
||||
if (exitCode !== 0) {
|
||||
throw new Error(`Selenium smoke exited with code ${exitCode}.`);
|
||||
}
|
||||
} finally {
|
||||
app.kill("SIGTERM");
|
||||
await delay(500);
|
||||
if (!app.killed) {
|
||||
app.kill("SIGKILL");
|
||||
}
|
||||
|
||||
if (fs.existsSync(tempDbPath)) {
|
||||
fs.rmSync(tempDbPath, { force: true });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
run().catch((error) => {
|
||||
console.error(error.stack || error);
|
||||
process.exitCode = 1;
|
||||
});
|
||||
Reference in New Issue
Block a user