update
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
Backup: message_badge_scroll_to_unread
|
||||
Erstellt: 20260613_192024
|
||||
Rollback: Dateien aus diesem Ordner zurueckkopieren
|
||||
@@ -0,0 +1,101 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Tests: Chat-Header (Größe, Online, Badges), Benutzerliste, Mini-Diktat Einfügen."""
|
||||
from __future__ import annotations
|
||||
|
||||
import inspect
|
||||
import re
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parent
|
||||
|
||||
|
||||
class EmpfangHtmlHeaderV4Tests(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.html = (ROOT / "web" / "empfang.html").read_text(encoding="utf-8")
|
||||
|
||||
def test_angemeldet_als_label_separate(self):
|
||||
self.assertIn('class="header-me-label">Angemeldet als</div>', self.html)
|
||||
self.assertIn('id="header-me-display"', self.html)
|
||||
|
||||
def test_display_name_larger_than_label(self):
|
||||
self.assertIn(".header-me-display{font-size:1.12rem", self.html)
|
||||
self.assertIn(".header-me-label{font-size:.68rem", self.html)
|
||||
|
||||
def test_online_presence_in_header(self):
|
||||
self.assertIn('id="header-me-presence"', self.html)
|
||||
self.assertIn(".header-me-presence.online{", self.html)
|
||||
self.assertIn(
|
||||
"el.className = 'header-me-presence ' + (online ? 'online' : 'offline')",
|
||||
self.html,
|
||||
)
|
||||
self.assertIn('html[data-empfang-chat-shell="1"] #sidebar .sb-me-detail{display:none!important}', self.html)
|
||||
|
||||
def test_badges_in_header_with_messages(self):
|
||||
self.assertIn("sb-me-pill-msgs", self.html)
|
||||
self.assertIn("navigateFromMessagesBadgeClick", self.html)
|
||||
self.assertIn("refreshMeStatusBadgesAll", self.html)
|
||||
|
||||
def test_load_tasks_refreshes_header_badges(self):
|
||||
self.assertIn("refreshMeStatusBadgesAll(); } catch (_eBdT)", self.html)
|
||||
|
||||
def test_no_duplicate_sidebar_badges_in_shell(self):
|
||||
m = re.search(
|
||||
r"function renderSbMeStatusBadges\(\)\s*\{([\s\S]*?)\n\}",
|
||||
self.html,
|
||||
)
|
||||
self.assertIsNotNone(m)
|
||||
self.assertIn("isDesktopShellMode()", m.group(1))
|
||||
|
||||
def test_users_panel_dynamic_title(self):
|
||||
self.assertIn('id="sb-users-panel-title"', self.html)
|
||||
self.assertIn("Benutzer der Praxis:", self.html)
|
||||
self.assertIn("function updateSbUsersPanelTitle", self.html)
|
||||
|
||||
def test_explanation_text_removed(self):
|
||||
self.assertNotIn("Gleicher Datenraum wie in AzA", self.html)
|
||||
self.assertIn('id="sb-users-hint"', self.html)
|
||||
self.assertIn('id="sb-users-hint" aria-live="polite" style="display:none"', self.html)
|
||||
|
||||
|
||||
class MiniDiktatPasteTests(unittest.TestCase):
|
||||
def test_paste_helpers_exist(self):
|
||||
import aza_mini_diktat_window as md
|
||||
|
||||
self.assertTrue(callable(getattr(md, "_paste_into_diktat_text", None)))
|
||||
self.assertTrue(callable(getattr(md, "_bind_mini_diktat_context_paste", None)))
|
||||
|
||||
def test_context_menu_wired_on_open(self):
|
||||
import aza_mini_diktat_window as md
|
||||
|
||||
open_src = inspect.getsource(md.open_mini_diktat_window)
|
||||
bind_src = inspect.getsource(md._bind_mini_diktat_context_paste)
|
||||
self.assertIn("_bind_mini_diktat_context_paste", open_src)
|
||||
self.assertIn("Einfügen", bind_src)
|
||||
self.assertIn("<Button-3>", bind_src)
|
||||
|
||||
def test_diktat_text_reference_on_window(self):
|
||||
import aza_diktat_mixin as dm
|
||||
|
||||
src = inspect.getsource(dm.AzaDiktatMixin.open_diktat_window)
|
||||
self.assertIn("_aza_diktat_text = txt", src)
|
||||
|
||||
def test_paste_uses_clipboard_and_insert(self):
|
||||
import aza_mini_diktat_window as md
|
||||
|
||||
src = inspect.getsource(md._paste_into_diktat_text)
|
||||
self.assertIn("clipboard_get", src)
|
||||
self.assertIn("txt.insert", src)
|
||||
|
||||
|
||||
class EmpfangHtmlJsSyntaxTests(unittest.TestCase):
|
||||
def test_inline_script_brace_balance(self):
|
||||
html = (ROOT / "web" / "empfang.html").read_text(encoding="utf-8")
|
||||
scripts = re.findall(r"<script(?:[^>]*)>([\s\S]*?)</script>", html, flags=re.I)
|
||||
combined = "\n".join(scripts)
|
||||
self.assertEqual(combined.count("{"), combined.count("}"))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -0,0 +1,187 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Tests: Aufgaben-Antwortverlauf, Badge-Handoffs, fester Header, Branding, Mini-Diktat-Parität."""
|
||||
from __future__ import annotations
|
||||
|
||||
import inspect
|
||||
import re
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parent
|
||||
|
||||
|
||||
class EmpfangHtmlTaskReplyTests(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.html = (ROOT / "web" / "empfang.html").read_text(encoding="utf-8")
|
||||
|
||||
def test_reply_block_uses_display_name_colon_format(self):
|
||||
self.assertIn("function formatTaskReplyBlock", self.html)
|
||||
m = re.search(
|
||||
r"function formatTaskReplyBlock\([^)]*\)\s*\{([\s\S]*?)\n\}",
|
||||
self.html,
|
||||
)
|
||||
self.assertIsNotNone(m, "formatTaskReplyBlock nicht gefunden")
|
||||
body = m.group(1)
|
||||
self.assertIn("resolveCanonicalAssigneeName", body)
|
||||
self.assertIn("': '", body)
|
||||
self.assertNotIn("antwortet", body)
|
||||
|
||||
def test_reply_append_guard_and_persist_order(self):
|
||||
self.assertIn("_taskReplyInFlight", self.html)
|
||||
m = re.search(
|
||||
r"async function taskEditorAppendReply\(\)\s*\{([\s\S]*?)\n\}",
|
||||
self.html,
|
||||
)
|
||||
self.assertIsNotNone(m)
|
||||
body = m.group(1)
|
||||
self.assertIn("_taskReplyInFlight = true", body)
|
||||
self.assertIn("persistTaskFromEditor", body)
|
||||
clear_idx = body.find("replyTa.value = ''")
|
||||
persist_idx = body.find("persistTaskFromEditor")
|
||||
self.assertGreater(clear_idx, persist_idx, "Antwortfeld erst nach Erfolg leeren")
|
||||
self.assertIn("bodyTa.value = prevBody", body)
|
||||
|
||||
def test_reply_uses_current_session_display_name(self):
|
||||
self.assertIn(
|
||||
"formatTaskReplyBlock(currentSession ? currentSession.display_name : ''",
|
||||
self.html,
|
||||
)
|
||||
|
||||
|
||||
class EmpfangHtmlBadgeHandoffTests(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.html = (ROOT / "web" / "empfang.html").read_text(encoding="utf-8")
|
||||
|
||||
def test_kontakt_panel_nav_open_handoff(self):
|
||||
self.assertIn("function kontaktPanelNavigateFromBadge", self.html)
|
||||
self.assertIn("/shell/nav-open", self.html)
|
||||
self.assertIn("focus_empfang_chat_shell", self.html)
|
||||
|
||||
def test_navigate_delegates_in_kontakt_panel(self):
|
||||
m = re.search(
|
||||
r"function navigateFromTaskBadgeClick\([^)]*\)\s*\{([\s\S]*?)\n\}",
|
||||
self.html,
|
||||
)
|
||||
self.assertIsNotNone(m)
|
||||
body = m.group(1)
|
||||
self.assertIn("isKontaktPanelMode()", body)
|
||||
self.assertIn("kontaktPanelNavigateFromBadge", body)
|
||||
|
||||
def test_shell_context_consumes_nav_open(self):
|
||||
self.assertIn("nav_open_kind", self.html)
|
||||
self.assertIn("navigateFromTaskBadgeClick(navKind", self.html)
|
||||
|
||||
def test_badges_clickable_with_keyboard(self):
|
||||
self.assertIn("bindTaskBadgeKeyboard", self.html)
|
||||
self.assertIn('role="button"', self.html)
|
||||
self.assertIn("sb-me-pill-tasks", self.html)
|
||||
self.assertIn("sb-me-pill-letters", self.html)
|
||||
|
||||
|
||||
class EmpfangHtmlHeaderTests(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.html = (ROOT / "web" / "empfang.html").read_text(encoding="utf-8")
|
||||
|
||||
def test_fixed_header_user_block(self):
|
||||
self.assertIn('id="header-user-block"', self.html)
|
||||
self.assertIn('id="header-me-display"', self.html)
|
||||
self.assertIn("function updateHeaderMeBlock", self.html)
|
||||
self.assertIn("Angemeldet als", self.html)
|
||||
|
||||
def test_sidebar_detail_hidden_in_shell(self):
|
||||
self.assertIn("#sidebar .sb-me-detail", self.html)
|
||||
self.assertIn("display:none!important", self.html)
|
||||
|
||||
def test_header_badges_reuse_navigate(self):
|
||||
self.assertIn("renderMeStatusBadgesHtml", self.html)
|
||||
self.assertIn("navigateFromTaskBadgeClick", self.html)
|
||||
|
||||
|
||||
class EmpfangHtmlBrandingTests(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.html = (ROOT / "web" / "empfang.html").read_text(encoding="utf-8")
|
||||
|
||||
def test_visible_title_aza_chat(self):
|
||||
self.assertIn("<title>AzA Chat</title>", self.html)
|
||||
self.assertIn("<h1>AzA Chat</h1>", self.html)
|
||||
self.assertNotIn("AzA-Empfang", self.html)
|
||||
|
||||
def test_empfang_routes_unchanged_in_html(self):
|
||||
self.assertIn("/empfang/", self.html)
|
||||
|
||||
|
||||
class EmpfangRoutesNavOpenTests(unittest.TestCase):
|
||||
def test_nav_open_route_exists(self):
|
||||
src = (ROOT / "empfang_routes.py").read_text(encoding="utf-8")
|
||||
self.assertIn('@router.post("/shell/nav-open")', src)
|
||||
self.assertIn("nav_open_kind", src)
|
||||
self.assertIn("nav_open_assignee", src)
|
||||
|
||||
def test_context_me_returns_nav_fields(self):
|
||||
src = (ROOT / "empfang_routes.py").read_text(encoding="utf-8")
|
||||
self.assertIn('"nav_open_kind": nav_kind_out', src)
|
||||
self.assertIn('"nav_open_assignee": nav_assignee_out', src)
|
||||
|
||||
|
||||
class MiniDiktatParityTests(unittest.TestCase):
|
||||
def test_same_window_size_as_aza_mini(self):
|
||||
import aza_mini_diktat_window as md
|
||||
import aza_mini_record_window as mr
|
||||
|
||||
self.assertEqual(md._MINI_WIN_W, mr._MINI_WIN_W)
|
||||
self.assertEqual(md._MINI_WIN_H, mr._MINI_WIN_H)
|
||||
self.assertEqual(md._MINI_WIN_W, 236)
|
||||
self.assertEqual(md._MINI_WIN_H, 210)
|
||||
|
||||
def test_mini_diktat_labels_and_chrome(self):
|
||||
import aza_mini_diktat_window as md
|
||||
|
||||
src = inspect.getsource(md.open_mini_diktat_window)
|
||||
self.assertIn('win.title("Mini-Diktat")', src)
|
||||
self.assertIn('text="Mini-Diktat"', src)
|
||||
self.assertIn('text="Weiterfahren"', src)
|
||||
self.assertIn("Logo3.png", md._LOGO_CANDIDATES)
|
||||
|
||||
def test_status_states(self):
|
||||
import aza_mini_diktat_window as md
|
||||
|
||||
src = inspect.getsource(md)
|
||||
self.assertIn("Bereit", src)
|
||||
self.assertIn("Aufnahme läuft …", src)
|
||||
self.assertIn("_diktat_status_text", src)
|
||||
self.assertIn("_aza_diktat_status_var", src)
|
||||
|
||||
def test_diktat_button_renamed(self):
|
||||
import aza_diktat_mixin as dm
|
||||
|
||||
src = inspect.getsource(dm.AzaDiktatMixin.open_diktat_window)
|
||||
self.assertIn('text="Mini-Diktat"', src)
|
||||
|
||||
def test_korrigieren_wires_existing_path(self):
|
||||
import aza_mini_diktat_window as md
|
||||
|
||||
src = inspect.getsource(md.open_mini_diktat_window)
|
||||
self.assertIn("_aza_diktat_weiterfahren", src)
|
||||
self.assertIn("_aza_diktat_korrigieren", src)
|
||||
self.assertIn("Weiterfahren", src)
|
||||
|
||||
def test_main_mini_unchanged_size(self):
|
||||
import aza_mini_record_window as mr
|
||||
|
||||
self.assertEqual(mr._MINI_WIN_W, 236)
|
||||
|
||||
|
||||
class WebviewBrandingTests(unittest.TestCase):
|
||||
def test_window_titles(self):
|
||||
from aza_empfang_webview import _window_title_for_mode, _MODE_DESKTOP_SHELL
|
||||
|
||||
self.assertEqual(_window_title_for_mode(_MODE_DESKTOP_SHELL), "AzA Chat · Desktop")
|
||||
self.assertEqual(_window_title_for_mode(""), "AzA Chat")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -0,0 +1,67 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Tests für Update-Badge statt Startup-Popup."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import unittest
|
||||
|
||||
|
||||
class TestUpdateBadgeLogic(unittest.TestCase):
|
||||
def test_startup_dialog_suppressed_for_optional_only(self):
|
||||
from desktop_update_check import _startup_should_show_dialog
|
||||
|
||||
optional = {"update_level": "optional", "below_min_required": False}
|
||||
required = {"update_level": "required", "below_min_required": False}
|
||||
self.assertFalse(_startup_should_show_dialog(optional))
|
||||
self.assertTrue(_startup_should_show_dialog(required))
|
||||
|
||||
def test_startup_should_show_dialog_optional_false(self):
|
||||
from desktop_update_check import _startup_should_show_dialog
|
||||
|
||||
info = {"update_level": "optional", "below_min_required": False}
|
||||
self.assertFalse(_startup_should_show_dialog(info))
|
||||
|
||||
def test_startup_should_show_dialog_required_true(self):
|
||||
from desktop_update_check import _startup_should_show_dialog
|
||||
|
||||
info = {"update_level": "required", "below_min_required": False}
|
||||
self.assertTrue(_startup_should_show_dialog(info))
|
||||
|
||||
def test_show_update_dialog_from_info_requires_info(self):
|
||||
from desktop_update_check import show_update_dialog_from_info
|
||||
|
||||
# Kein Parent/Dialog ohne info — darf nicht crashen.
|
||||
show_update_dialog_from_info(None, parent=None)
|
||||
|
||||
def test_startup_dialog_does_not_open_ui(self):
|
||||
"""Optionale/recommended Updates: kein Startup-Popup (Badge stattdessen)."""
|
||||
import desktop_update_check as duc
|
||||
|
||||
doc = duc.maybe_show_startup_update_dialog.__doc__ or ""
|
||||
self.assertTrue("kein Popup" in doc or "Badge" in doc or "Pflicht" in doc)
|
||||
|
||||
def test_no_aktuell_label_in_update_hint_logic(self):
|
||||
"""Ohne Update: kein sichtbarer Aktuell-Text, kein Status-Label."""
|
||||
import inspect
|
||||
|
||||
import aza_office_shell_v1 as shell
|
||||
|
||||
src = inspect.getsource(shell._OfficeShellV12._apply_update_hint)
|
||||
self.assertNotIn("Aktuell", src)
|
||||
self.assertNotIn("_sidebar_update_status", src)
|
||||
|
||||
def test_recommended_update_no_startup_dialog(self):
|
||||
from desktop_update_check import _startup_should_show_dialog
|
||||
|
||||
info = {"update_level": "recommended", "below_min_required": False}
|
||||
self.assertFalse(_startup_should_show_dialog(info))
|
||||
|
||||
def test_below_min_required_still_shows_startup_dialog(self):
|
||||
from desktop_update_check import _startup_should_show_dialog
|
||||
|
||||
info = {"update_level": "recommended", "below_min_required": True}
|
||||
self.assertTrue(_startup_should_show_dialog(info))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,212 @@
|
||||
# Lokaler Dev-Start: Konsistenter Office-Release-Candidate v5 (Stable 1.3.12 unveraendert)
|
||||
# Startet zuerst den lokalen HTML-Proxy als persistenten Prozess, wartet auf HTTP 200, dann Desktop.
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
function Write-TestLog {
|
||||
param([string]$Message)
|
||||
Write-Host ("[{0}] {1}" -f (Get-Date -Format "yyyy-MM-dd HH:mm:ss.fff"), $Message)
|
||||
}
|
||||
|
||||
$env:AZA_DOKU_PROMPT_TEST = "1"
|
||||
$ProjectRoot = $PSScriptRoot
|
||||
Set-Location $ProjectRoot
|
||||
|
||||
Write-Host "Starte AzA Testbuild test_final_release_candidate_v9 (Stable 1.3.12 unveraendert)..."
|
||||
|
||||
$testExe = Join-Path $ProjectRoot "dist\test_final_release_candidate_v9\aza_desktop.exe"
|
||||
if (-not (Test-Path $testExe)) {
|
||||
Write-Error "Testbuild nicht gefunden: $testExe`nBitte zuerst build_test_final_release_candidate_v9.ps1 ausfuehren."
|
||||
exit 1
|
||||
}
|
||||
|
||||
$shellExe = Join-Path (Split-Path $testExe) "AZA_EmpfangShell.exe"
|
||||
$panelExe = Join-Path (Split-Path $testExe) "AZA_KontaktPanel.exe"
|
||||
if (-not (Test-Path $shellExe)) {
|
||||
Write-Warning "AZA_EmpfangShell.exe fehlt neben dem Testbuild: $shellExe"
|
||||
}
|
||||
if (-not (Test-Path $panelExe)) {
|
||||
Write-Warning "AZA_KontaktPanel.exe fehlt neben dem Testbuild: $panelExe"
|
||||
}
|
||||
|
||||
# Upstream-API (backend_url.txt)
|
||||
$upstream = "https://api.aza-medwork.ch"
|
||||
$backendFile = Join-Path $ProjectRoot "backend_url.txt"
|
||||
if (Test-Path $backendFile) {
|
||||
$line = Get-Content $backendFile -ErrorAction SilentlyContinue | Where-Object { $_ -and -not $_.StartsWith("#") } | Select-Object -First 1
|
||||
if ($line) { $upstream = $line.Trim().TrimEnd("/") }
|
||||
}
|
||||
$env:AZA_EMPFANG_TEST_UPSTREAM = $upstream
|
||||
|
||||
# Python + Proxy-Skript (absolute Pfade)
|
||||
$pythonExe = (Get-Command python -ErrorAction Stop).Source
|
||||
$proxyScript = Join-Path $ProjectRoot "aza_empfang_test_html_proxy.py"
|
||||
if (-not (Test-Path $proxyScript)) {
|
||||
Write-Error "Proxy-Skript fehlt: $proxyScript"
|
||||
exit 1
|
||||
}
|
||||
|
||||
$logDir = Join-Path $ProjectRoot ".aza_test_proxy_logs"
|
||||
New-Item -ItemType Directory -Path $logDir -Force | Out-Null
|
||||
$ts = Get-Date -Format "yyyyMMdd_HHmmss"
|
||||
$stdoutLog = Join-Path $logDir "proxy_stdout_$ts.log"
|
||||
$stderrLog = Join-Path $logDir "proxy_stderr_$ts.log"
|
||||
|
||||
# Veraltete Test-Proxy-Prozesse beenden: sonst bedient ein frueher gestarteter
|
||||
# Proxy (mit altem Code im Speicher) denselben Port und bricht SSO/Redirect.
|
||||
try {
|
||||
$staleProxies = Get-CimInstance Win32_Process -Filter "Name='python.exe'" -ErrorAction SilentlyContinue |
|
||||
Where-Object { $_.CommandLine -and ($_.CommandLine -match 'aza_empfang_test_html_proxy\.py') }
|
||||
foreach ($sp in $staleProxies) {
|
||||
Write-Host ("Beende veralteten Test-Proxy PID {0}" -f $sp.ProcessId)
|
||||
Stop-Process -Id $sp.ProcessId -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
if ($staleProxies) { Start-Sleep -Milliseconds 500 }
|
||||
} catch {
|
||||
Write-Warning ("Stale-Proxy-Cleanup uebersprungen: {0}" -f $_.Exception.Message)
|
||||
}
|
||||
|
||||
Write-Host "Starte Test-HTML-Proxy (persistenter Prozess)..."
|
||||
Write-Host " Python: $pythonExe"
|
||||
Write-Host " Skript: $proxyScript"
|
||||
Write-Host " Upstream: $upstream"
|
||||
Write-Host " Log stdout: $stdoutLog"
|
||||
Write-Host " Log stderr: $stderrLog"
|
||||
|
||||
$proxyProc = Start-Process `
|
||||
-FilePath $pythonExe `
|
||||
-ArgumentList @("aza_empfang_test_html_proxy.py", "--serve") `
|
||||
-WorkingDirectory $ProjectRoot `
|
||||
-PassThru `
|
||||
-WindowStyle Hidden `
|
||||
-RedirectStandardOutput $stdoutLog `
|
||||
-RedirectStandardError $stderrLog
|
||||
|
||||
$proxyPort = $null
|
||||
$deadline = (Get-Date).AddSeconds(15)
|
||||
while ((Get-Date) -lt $deadline) {
|
||||
if ($proxyProc.HasExited) {
|
||||
$errTail = ""
|
||||
if (Test-Path $stderrLog) {
|
||||
$errTail = (Get-Content $stderrLog -Raw -ErrorAction SilentlyContinue)
|
||||
}
|
||||
$outTail = ""
|
||||
if (Test-Path $stdoutLog) {
|
||||
$outTail = (Get-Content $stdoutLog -Raw -ErrorAction SilentlyContinue)
|
||||
}
|
||||
Write-Error @"
|
||||
Test-HTML-Proxy-Prozess beendet (Exit $($proxyProc.ExitCode)) bevor READY.
|
||||
stdout: $stdoutLog
|
||||
stderr: $stderrLog
|
||||
--- stdout ---
|
||||
$outTail
|
||||
--- stderr ---
|
||||
$errTail
|
||||
"@
|
||||
exit 1
|
||||
}
|
||||
if (Test-Path $stdoutLog) {
|
||||
$out = Get-Content $stdoutLog -Raw -ErrorAction SilentlyContinue
|
||||
if ($out -match 'READY port=(\d+)') {
|
||||
$proxyPort = [int]$Matches[1]
|
||||
break
|
||||
}
|
||||
}
|
||||
Start-Sleep -Milliseconds 300
|
||||
}
|
||||
|
||||
if (-not $proxyPort) {
|
||||
if (-not $proxyProc.HasExited) {
|
||||
Stop-Process -Id $proxyProc.Id -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
Write-Error "Test-HTML-Proxy: READY-Timeout nach 15s. Logs: $stdoutLog / $stderrLog"
|
||||
exit 1
|
||||
}
|
||||
|
||||
$proxyBase = "http://127.0.0.1:$proxyPort"
|
||||
$healthUrl = "$proxyBase/health"
|
||||
$empfangUrl = "$proxyBase/empfang/"
|
||||
|
||||
Write-TestLog ("Proxy READY auf Port {0} (PID {1})" -f $proxyPort, $proxyProc.Id)
|
||||
|
||||
# HTTP-Healthcheck (zusaetzlich zur READY-Zeile)
|
||||
try {
|
||||
$healthResp = Invoke-WebRequest -Uri $healthUrl -UseBasicParsing -TimeoutSec 5
|
||||
if ($healthResp.StatusCode -ne 200) {
|
||||
throw "Health Status $($healthResp.StatusCode)"
|
||||
}
|
||||
Write-Host ("Healthcheck OK: {0}" -f $healthUrl)
|
||||
} catch {
|
||||
Stop-Process -Id $proxyProc.Id -Force -ErrorAction SilentlyContinue
|
||||
Write-Error ("Healthcheck fehlgeschlagen: {0} - {1}`nstderr: {2}" -f $healthUrl, $_.Exception.Message, $stderrLog)
|
||||
exit 1
|
||||
}
|
||||
|
||||
try {
|
||||
$htmlResp = Invoke-WebRequest -Uri $empfangUrl -UseBasicParsing -TimeoutSec 8
|
||||
if ($htmlResp.StatusCode -ne 200) {
|
||||
throw "Empfang HTML Status $($htmlResp.StatusCode)"
|
||||
}
|
||||
if ($htmlResp.Headers["Cache-Control"] -notmatch "no-store") {
|
||||
Write-Warning "Empfang HTML ohne Cache-Control no-store (weiterhin OK)"
|
||||
}
|
||||
Write-Host ("Empfang HTML OK: {0} ({1} Bytes)" -f $empfangUrl, $htmlResp.RawContentLength)
|
||||
} catch {
|
||||
Stop-Process -Id $proxyProc.Id -Force -ErrorAction SilentlyContinue
|
||||
Write-Error ("Empfang-HTML-Check fehlgeschlagen: {0} - {1}`nstderr: {2}" -f $empfangUrl, $_.Exception.Message, $stderrLog)
|
||||
exit 1
|
||||
}
|
||||
|
||||
$env:AZA_EMPFANG_TEST_PROXY_PORT = [string]$proxyPort
|
||||
$env:AZA_EMPFANG_WEB_BASE = $proxyBase
|
||||
$env:AZA_EMPFANG_CHAT_SHELL_URL = "$proxyBase/empfang/"
|
||||
|
||||
Write-Host "Umgebung gesetzt:"
|
||||
Write-Host " AZA_EMPFANG_WEB_BASE=$($env:AZA_EMPFANG_WEB_BASE)"
|
||||
Write-Host " AZA_EMPFANG_CHAT_SHELL_URL=$($env:AZA_EMPFANG_CHAT_SHELL_URL)"
|
||||
Write-TestLog "Starte Desktop-Testbuild..."
|
||||
|
||||
try {
|
||||
$desktopProc = Start-Process `
|
||||
-FilePath $testExe `
|
||||
-WorkingDirectory (Split-Path $testExe) `
|
||||
-PassThru
|
||||
|
||||
Write-TestLog ("Desktop-Prozess gestartet (PID {0})" -f $desktopProc.Id)
|
||||
Start-Sleep -Seconds 2
|
||||
|
||||
if ($proxyProc.HasExited) {
|
||||
Write-Error ("Proxy beendet unerwartet nach Desktopstart. stderr: {0}" -f $stderrLog)
|
||||
exit 1
|
||||
}
|
||||
|
||||
$postHealth = Invoke-WebRequest -Uri $healthUrl -UseBasicParsing -TimeoutSec 5
|
||||
if ($postHealth.StatusCode -ne 200) {
|
||||
throw ("Post-Desktop Health Status {0}" -f $postHealth.StatusCode)
|
||||
}
|
||||
Write-TestLog ("Proxy nach Desktopstart erreichbar: health {0}" -f $postHealth.StatusCode)
|
||||
|
||||
$postHtml = Invoke-WebRequest -Uri $empfangUrl -UseBasicParsing -TimeoutSec 8
|
||||
if ($postHtml.StatusCode -ne 200) {
|
||||
throw ("Post-Desktop Empfang Status {0}" -f $postHtml.StatusCode)
|
||||
}
|
||||
Write-TestLog ("Proxy Empfang nach Desktopstart: {0} ({1} Bytes)" -f $postHtml.StatusCode, $postHtml.RawContentLength)
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "V5-Test laeuft."
|
||||
Write-Host "Proxy bleibt aktiv."
|
||||
Write-Host "Nach Abschluss aller AzA-Testfenster hier ENTER druecken, um den Proxy zu beenden."
|
||||
Write-Host ""
|
||||
Read-Host | Out-Null
|
||||
} finally {
|
||||
Write-TestLog ("Beende Test-HTML-Proxy (PID {0})..." -f $proxyProc.Id)
|
||||
if (-not $proxyProc.HasExited) {
|
||||
Stop-Process -Id $proxyProc.Id -Force -ErrorAction SilentlyContinue
|
||||
Start-Sleep -Milliseconds 200
|
||||
}
|
||||
if (-not $proxyProc.HasExited) {
|
||||
Write-Warning ("Proxy-Prozess {0} laeuft noch - bitte manuell pruefen." -f $proxyProc.Id)
|
||||
} else {
|
||||
Write-Host "Proxy beendet."
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user