Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ jobs:
shell: bash
run: ./scripts/verify-windows-runtime.sh D:/b/release/bundle/nsis/Wisp_*-setup.exe --require-vulkan

- name: Smoke-test the packaged Windows app
- name: Smoke-test the packaged Windows frontend and close behavior
if: runner.os == 'Windows'
shell: pwsh
run: |
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/windows-vulkan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ jobs:
- name: Verify the installer runtime
shell: bash
run: ./scripts/verify-windows-runtime.sh D:/b/release/bundle/nsis/Wisp_*-setup.exe --require-vulkan
- name: Smoke-test the packaged app
- name: Smoke-test the packaged frontend and close behavior
shell: pwsh
run: |
$installer = Get-ChildItem 'D:\b\release\bundle\nsis\Wisp_*-setup.exe' | Select-Object -First 1
Expand Down
16 changes: 15 additions & 1 deletion app/src-tauri/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4508,6 +4508,19 @@ fn set_search_mode(state: State<'_, AppState>, mode: String) -> Result<(), Strin
Ok(())
}

/// Marks the first rendered frontend frame for the packaged Windows smoke test. Normal users keep
/// the regular title; CI opts in with an environment variable so it can distinguish a working UI
/// from a white WebView process that merely stayed alive.
#[tauri::command]
fn frontend_ready(window: tauri::WebviewWindow) -> Result<(), String> {
if std::env::var_os("WISP_SMOKE_TEST").is_some() {
window
.set_title("Wisp [ready]")
.map_err(|e| format!("could not mark the frontend ready: {e}"))?;
}
Ok(())
}

#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
tauri::Builder::default()
Expand Down Expand Up @@ -4694,7 +4707,8 @@ pub fn run() {
set_embedding_model,
delete_embedding_model,
search_mode,
set_search_mode
set_search_mode,
frontend_ready
])
.build(tauri::generate_context!())
.expect("error while building tauri application")
Expand Down
6 changes: 5 additions & 1 deletion app/src-tauri/tauri.conf.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
"width": 1040,
"height": 740,
"minWidth": 820,
"minHeight": 640
"minHeight": 640,
"additionalBrowserArgs": "--disable-features=msWebOOUI,msPdfOOUI,msSmartScreenProtection --disable-gpu"
}
],
"security": {
Expand All @@ -27,6 +28,9 @@
"bundle": {
"active": true,
"targets": ["nsis", "dmg"],
"windows": {
"minimumWebview2Version": "120.0.2210.61"
},
"resources": [
"resources/silero_vad.onnx"
],
Expand Down
16 changes: 15 additions & 1 deletion app/src/routes/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -1359,10 +1359,24 @@
ensureProgressListener();
ensureFileListeners();
syncRunning();
// The packaged Windows test waits for this native title marker before it accepts startup. Two
// animation frames prove Svelte mounted and WebView2 completed a real paint; a white/hung
// renderer never reaches the command. Outside that opt-in test the backend leaves the title
// unchanged.
let readyFrame = requestAnimationFrame(() => {
readyFrame = requestAnimationFrame(() => {
void invoke("frontend_ready").catch(() => {
/* diagnostic-only handshake; never disrupt the real UI */
});
});
});
// Re-check when the window regains focus, so granting in System Settings clears the banner.
const onFocus = () => checkPermissions();
window.addEventListener("focus", onFocus);
return () => window.removeEventListener("focus", onFocus);
return () => {
cancelAnimationFrame(readyFrame);
window.removeEventListener("focus", onFocus);
};
});
onDestroy(() => {
unlisten?.();
Expand Down
30 changes: 27 additions & 3 deletions scripts/smoke-windows-installer.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ param(
)

$ErrorActionPreference = "Stop"
$readyTitle = "Wisp [ready]"

if (-not (Test-Path -LiteralPath $Installer -PathType Leaf)) {
throw "Windows installer not found: $Installer"
}

$extractDirectory = Join-Path ([System.IO.Path]::GetTempPath()) "wisp-windows-smoke-$([guid]::NewGuid())"
$process = $null
$previousSmokeTest = $env:WISP_SMOKE_TEST

try {
New-Item -ItemType Directory -Path $extractDirectory | Out-Null
Expand All @@ -20,14 +22,36 @@ try {
}

$executable = Join-Path $extractDirectory "Wisp.exe"
$env:WISP_SMOKE_TEST = "1"
$process = Start-Process -FilePath $executable -WorkingDirectory $extractDirectory -PassThru
if ($process.WaitForExit(15000)) {
throw "Packaged Wisp.exe exited during startup with code $($process.ExitCode)"

$readyDeadline = [DateTime]::UtcNow.AddSeconds(30)
do {
if ($process.HasExited) {
throw "Packaged Wisp.exe exited during startup with code $($process.ExitCode)"
}
$process.Refresh()
if ($process.MainWindowTitle -eq $readyTitle -and $process.MainWindowHandle -ne [IntPtr]::Zero) {
break
}
Start-Sleep -Milliseconds 250
} while ([DateTime]::UtcNow -lt $readyDeadline)

if ($process.MainWindowTitle -ne $readyTitle -or $process.MainWindowHandle -eq [IntPtr]::Zero) {
throw "Packaged Wisp.exe did not render its frontend within 30 seconds"
}

if (-not $process.CloseMainWindow()) {
throw "Packaged Wisp.exe did not accept a close request"
}
if (-not $process.WaitForExit(10000)) {
throw "Packaged Wisp.exe rendered but its window became unresponsive while closing"
}

Write-Host "Packaged Wisp.exe remained running for 15 seconds"
Write-Host "Packaged Wisp.exe rendered its frontend and closed responsively"
}
finally {
$env:WISP_SMOKE_TEST = $previousSmokeTest
if ($null -ne $process -and -not $process.HasExited) {
Stop-Process -Id $process.Id -Force
$process.WaitForExit()
Expand Down
Loading