Notatka
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Sprawdzanie i interakcja z uruchamianiem aplikacji Windows z poziomu wiersza polecenia. Używane przez agentów sztucznej inteligencji i deweloperów do testowania, debugowania i automatyzacji interfejsu użytkownika.
Przegląd
winapp ui udostępnia polecenia do inspekcji i interakcji z interfejsami użytkownika aplikacji Windows.
Używa Windows automatyzacja interfejsu użytkownika (UIA). Współpracuje z dowolną aplikacją Windows — WPF, WinForms, Win32, Electron i WinUI 3.
Większość poleceń napędza aplikację za pomocą wzorców interfejsu użytkownika (bez iniekcji danych wejściowych); ui click jest wyjątkiem i używa rzeczywistej symulacji myszy dla kontrolek, które nie obsługują InvokePattern.
Szybki start
# Connect to any app and see its UI tree
winapp ui inspect -a notepad
# Find specific elements
winapp ui search Button -a notepad
# Activate an element
winapp ui invoke Close -a notepad
# Take a screenshot
winapp ui screenshot -a notepad
Określanie wartości docelowej aplikacji
Według nazwy procesu
winapp ui inspect -a notepad
winapp ui inspect -a slack # auto-picks visible window for multi-process apps
winapp ui inspect -a imageresizer # partial match: finds PowerToys.ImageResizer
Według tytułu okna
winapp ui inspect -a "LICENSE - Notepad"
winapp ui inspect -a "Fix WinApp" # partial title match
Według identyfikatora PID
winapp ui inspect -a 12345
Przez HWND (stabilny — przetrwa zmiany tabulatora/tytułu)
# Discover HWNDs
winapp ui list-windows -a Terminal
→ HWND 985238: "🤖 Testing" (WindowsTerminal, PID 21228)
→ HWND 131906: "Fix WinApp" (WindowsTerminal, PID 21228)
# Target specific window
winapp ui inspect -w 131906
winapp ui screenshot -w 131906
Służy -a do odnajdywania w -w celu uzyskania stabilnego określania wartości docelowej. Gdy -a pasuje do wielu okien, polecenie wyświetla je z HWNDs, które chcesz wybrać.
Selektory
Elementy docelowe przy użyciu selektora wyświetlanego w [brackets] danych wyjściowych inspekcji/wyszukiwania.
Istnieją trzy typy selektorów:
| Selector | Znaczenie | Example |
|---|---|---|
MinimizeButton |
AutomationId (wyświetlany, gdy unikatowy — stabilny, preferowany) | winapp ui invoke MinimizeButton -a myapp |
btn-close-d1a0 |
Slug semantyczny (pokazany, gdy nie ma unikatowego identyfikatora AutomationId) | winapp ui invoke btn-close-d1a0 -a myapp |
Submit |
Wyszukiwanie w postaci zwykłego tekstu względem parametru Name/AutomationId (podciąg bez uwzględniania wielkości liter) | winapp ui invoke Submit -a myapp |
Selektory AutomationId to identyfikatory zestawu deweloperów (AutomationProperties.AutomationId w języku XAML).
Gdy identyfikator AutomationId jest unikatowy w całym drzewie interfejsu inspect użytkownika i search wyświetla go bezpośrednio jako selektor — te zmiany układu przetrwania, lokalizacja i restrukturyzacja drzewa.
Selektory Slug (np. ) są generowane, btn-close-d1a0gdy nie istnieje unikatowy identyfikator AutomationId.
Format: prefix-name-hash. Skrót weryfikuje tożsamość elementu, ale może przestarzał po zmianie interfejsu użytkownika.
Sprawdzanie formatu danych wyjściowych
Polecenie inspect wyświetla drzewo elementów z kolorowymi danymi wyjściowymi (selektor w cyjanku, nazwa na zielono, metadane w kolorze szarym):
TabView Tab (0,-1 1200x48)
TabListView List (4,-1 1100x48)
tab-newtab-5f5b TabItem "New Tab" (14,-1 200x48)
NewTabButton SplitButton "New Tab" [collapsed] (1104,5 96x36)
Found 10 elements (--depth 3). Use the first token as selector, e.g.: winapp ui invoke TabView -a terminal
Pierwszym wyrazem w każdym wierszu jest selektor — użyj go z innymi ui poleceniami.
Gdy element ma unikatowy identyfikator AutomationId, jest używany bezpośrednio (np. TabView, NewTabButton).
Jeśli nie istnieje unikatowy identyfikator AutomationId, jest używany wygenerowany ślimak (np. tab-newtab-5f5b).
Slugi semantyczne
Slugi używają formatu: prefix-normalizedname-hash gdzie:
- prefiks — 3-literowy skrót typu (btn, txt, chk, cmb, itm, tab, img, lbl, pn, win, grp, lnk, mnu itp.)
- normalizedname — małe litery alfanumeryczne z identyfikatora AutomationId (preferowane) lub nazwa, maksymalnie 15 znaków
- hash — skrót 4-znakowy skrót szesnastkowy identyfikatora RuntimeId elementu (weryfikuje tożsamość elementu)
Slugi są bezpieczne za pomocą powłoki (bez znaków specjalnych), unikatowe i mogą być używane bezpośrednio jako argumenty. Skrót zapewnia wykrywanie nieaktualności — jeśli element został zastąpiony, otrzymasz: "Element mógł ulec zmianie. Uruchom ponownie inspekcję".
Elementy bez nazwy lub AutomationId pokazują tylko prefiks + skrót (np. pn-c8a3).
Uściślanie wielu dopasowań
Slugi z inspect/search danych wyjściowych są unikatowe, ale mogą zmieniać się między zmianami układu — używają ich w zwykłych nazwach typów lub tekście, gdy wiele dopasowań. Gdy selektor jest niejednoznaczny, interfejs wiersza polecenia drukuje wszystkie dopasowania ze swoimi ślimakami, aby można było wybrać właściwy i ponownie uruchomić z tym ślimakiem.
winapp ui search Button -a myapp # shows: btn-ok-a1b2 "OK", btn-cancel-c3d4 "Cancel"
winapp ui invoke btn-ok-a1b2 -a myapp # invoke using slug (preferred)
winapp ui invoke btn-cancel-c3d4 -a myapp # invoke the other Button by its slug
Wyszukiwanie zwykłego tekstu
Użyj zwykłego tekstu, aby wyszukać elementy — nie jest wymagana żadna specjalna składnia:
winapp ui search Minimize -a notepad # finds elements with "Minimize" in Name or AutomationId
winapp ui search Close -a notepad # case-insensitive substring match
winapp ui invoke Minimize -a notepad # search + invoke in one step (disambiguates if needed)
winapp ui search "Save" -a notepad # find elements containing "Save"
winapp ui search "error" -a myapp # case-insensitive match
Gdy wyszukiwanie tekstu pasuje do wielu elementów (np. SettingsExpander, gdzie grupa, przycisk i tekst mają taką samą nazwę), interfejs wiersza polecenia automatycznie wybiera jedyny element wywołujący. Jeśli wiele jest wywoływanych, wyświetla listę wszystkich dopasowań z ślimakami.
W przypadku wyników wyszukiwania niepodwoływalnych (np. textblock wewnątrz przycisku) wyszukiwanie automatycznie wyświetla najbliższy nadrzędny element — element nadrzędny, którego można użyć z elementem invoke.
Działa to dla wszystkich selektorów wyszukiwania:
lbl-savechanges-a1b2 "Save changes" (120,40 80x20)
^ invoke via: btn-save-c3d4 "Save"
Selektor powierzchniowy może być używany bezpośrednio:
winapp ui invoke btn-save-c3d4 -a myapp # invoke the parent Button
Komendy
stan
Połącz się z aplikacją i pokaż informacje o połączeniu.
winapp ui status -a notepad
winapp ui status -a notepad --json
Sprawdzić
Wyświetl drzewo elementów interfejsu użytkownika. Dane wyjściowe pokazują semantycznie slugi z wcięciem 2-spacji dla hierarchii:
winapp ui inspect -a notepad # full window tree, depth 3
winapp ui inspect -a notepad --depth 5 # deeper tree
winapp ui inspect txt-searchbox-e5f6 -a notepad # subtree rooted at element
winapp ui inspect --ancestors btn-close-d1a2 -a notepad # walk up from element to root
winapp ui inspect -a myapp --interactive # invokable elements only, auto-depth 8
winapp ui inspect -a myapp --hide-disabled # hide disabled elements
winapp ui inspect -a myapp --hide-offscreen # hide offscreen elements
Przykładowe dane wyjściowe (wartość domyślna):
win-aidevgalleryp-f1a3 "AI Dev Gallery Preview" (94,206 1280x1023)
pn-c8a3 (102,207 1264x1014)
btn-minimize-d1a0 "Minimize" (1222,206 48x48)
btn-maximize-e2b1 "Maximize" (1270,206 48x48)
itm-samples-3f2c "Samples" (102,330 72x62)
Przykładowe dane wyjściowe (--interactive — tylko elementy, lista płaska):
btn-minimize-d1a0 "Minimize" (1222,206 48x48)
btn-maximize-e2b1 "Maximize" (1270,206 48x48)
btn-close-d1a2 "Close" (1318,206 48x48)
itm-home-7b3e "Home" (102,268 72x62)
itm-samples-3f2c "Samples" (102,330 72x62)
itm-models-9a4f "Models" (102,392 72x62)
Elementy mogą pokazywać następujące znaczniki stanu:
-
[on]/[off]/[indeterminate]— stan przełącznika/pola wyboru -
[collapsed]/[expanded]— stan rozwijania/zwijania drzew, pól kombi, elementów menu -
[scroll:v]/[scroll:h]/[scroll:vh]— kontener przewijany (pionowy, poziomy lub oba) -
[offscreen]— element nie jest widoczny na ekranie -
[disabled]— element nie jest włączony -
value="..."— bieżąca zawartość tekstowa elementów edytowalnych (gdy różni się od nazwy)
wyszukać
Znajdowanie elementów pasujących do selektora. Dane wyjściowe pokazują semantycznie slugi:
winapp ui search Button -a notepad # all buttons
winapp ui search Close -a notepad # finds elements with "Close" in name
winapp ui search SearchBox -a notepad # finds elements with "SearchBox" in name or AutomationId
winapp ui search Button --max 10 -a notepad # limit results
Przykładowy wynik:
btn-minimize-d1a0 "Minimize" (1222,206 48x48)
btn-maximize-e2b1 "Maximize" (1270,206 48x48)
btn-close-d1a2 "Close" (1318,206 48x48)
Slugi wyświetlane w danych wyjściowych (np. btn-minimize-d1a0) mogą być używane bezpośrednio z innymi poleceniami:
winapp ui invoke btn-minimize-d1a0 -a notepad
get-property
Odczytywanie wartości właściwości z elementu. Obejmuje stan specyficzny dla wzorca (ToggleState, Value, IsSelected itp.).
winapp ui get-property btn-submit-7a90 -a myapp # all properties
winapp ui get-property chk-checkbox-b2c3 -p ToggleState -a myapp # checkbox state
winapp ui get-property txt-textbox-a4b1 -p Value -a myapp # current text value
winapp ui get-property cmb-combobox-d5e6 -p ExpandCollapseState -a myapp # expanded or collapsed
zrzut ekranu
Przechwyć okno lub element jako PNG. Gdy istnieje wiele okien (np. aplikacja + otwarte okno dialogowe), są one złożone w jeden plik PNG z każdym oknem zeszytymi.
winapp ui screenshot -a notepad # saves screenshot.png in cwd
winapp ui screenshot -a notepad --output my.png # custom filename
winapp ui screenshot -a notepad --json # returns file path as JSON
winapp ui screenshot -w 131906 # target specific HWND (+ its dialogs)
winapp ui screenshot txt-searchbox-e5f6 -a myapp # crop to element bounds
winapp ui screenshot -a myapp --capture-screen # capture from screen (includes popups/overlays)
Gdy okna dialogowe lub wyskakujące okienka są otwarte, wszystkie okna są złożone w jeden plik PNG, dzięki czemu można zobaczyć pełny stan interfejsu użytkownika w jednym obrazie.
Użyj --capture-screen polecenia , aby przechwycić menu podręczne, listy rozwijane, wysuwane lub nakładki etykietek narzędzi. W --capture-screen trybie (i po ponowieniu próby po wykryciu pustej ramki) okno docelowe zostanie przeniesione na pierwszy plan; zwykłe przechwytywanie okien nie przenosi okna.
wywołać
Programowe aktywowanie elementu (kliknij przycisk, przełącz pole wyboru, rozwiń pole kombi).
winapp ui invoke btn-submit-7a90 -a myapp # by slug from inspect
winapp ui invoke btn-submit-a1b2 -a myapp # by slug from inspect/search
winapp ui invoke cmb-sizecombobox-b4c5 -a myapp # expand combo box
Próbuje wzorce w kolejności: InvokePattern → TogglePattern → SelectionItemPattern → ExpandCollapsePattern.
click
Kliknij element na jego ekranie współrzędnych przy użyciu symulacji myszy. Służy do kontrolek, które nie obsługują InvokePattern (np. nagłówki kolumn, elementy listy).
winapp ui click btn-column1-a3f2 -a myapp # single click by slug
winapp ui click "Column1" -a myapp # single click by text search
winapp ui click btn-column1-a3f2 -a myapp --double # double-click
winapp ui click btn-column1-a3f2 -a myapp --right # right-click
set-value
Ustaw wartość na edytowalny element (tekst TextBox/ComboBox, liczba suwaka).
winapp ui set-value txt-textbox-a4b1 "Hello world" -a notepad
winapp ui set-value sld-volume-b2c3 75 -a myapp
get-value
Odczytaj bieżącą wartość z elementu. Używa inteligentnego łańcucha rezerwowego: TextPattern (RichEditBox, Document) → ValuePattern (TextBox, Slider) → SelectionPattern (ComboBox, RadioButton, TabView) → Name (etykiety).
winapp ui get-value doc-texteditor-53ad -a notepad # read full document text
winapp ui get-value SearchBox -a myapp # read TextBox content
winapp ui get-value CmbTheme -a myapp # read ComboBox selected item
winapp ui get-value sld-volume-b2c3 -a myapp # read Slider value
winapp ui get-value lbl-title-a1b2 -a myapp --json # JSON: { "elementId": "...", "text": "..." }
focus
Przenieś fokus klawiatury do elementu.
winapp ui focus txt-textbox-a4b1 -a notepad
przewiń do widoku
Przewiń element do widocznego obszaru.
winapp ui scroll-into-view itm-targetitem-c3d4 -a myapp
wait-for
Poczekaj, aż element pojawi się, zniknie lub osiągnie wartość docelową.
winapp ui wait-for Button -a myapp --timeout 5000 # wait for any button
winapp ui wait-for btn-submit-7a90 -a myapp --timeout 5000 # wait for specific element
winapp ui wait-for CounterDisplay -a myapp --value "5" --timeout 5000 # wait for element value (smart fallback)
winapp ui wait-for lbl-status -a myapp --property Name --value "Done" --timeout 5000 # wait for specific property
winapp ui wait-for btn-submit-a1b2 --gone -a myapp --timeout 2000 # wait for element to disappear
winapp ui wait-for lbl-status -a myapp --value "Done" --contains # substring match instead of exact equality
Przewiń
Przewiń element kontenera. Znajdź kontenery search scroll z możliwością przewijania — poszukaj [scroll:v] (pionowych) lub [scroll:h] (poziomych) znaczników.
# Find which elements are scrollable and in which direction
winapp ui search scroll -a myapp
# pn-scrollview-bfef Pane "scrollView" [scroll:v] (main content, vertical)
# pn-scrollviewer-bfb1 Pane "scrollViewer" [scroll:h] (horizontal list)
# Scroll the main content down
winapp ui scroll pn-scrollview-bfef --direction down -a myapp
# Jump to top/bottom
winapp ui scroll pn-scrollview-bfef --to bottom -a myapp
# If you target an element that's not scrollable, scroll walks up to find the nearest scrollable parent
winapp ui scroll itm-someitem-a1b2 --direction down -a myapp
uzyskiwanie fokusu
Pokaż element, który obecnie ma fokus klawiatury.
winapp ui get-focused -a myapp
list-windows
Wyświetl listę wszystkich widocznych okien dla aplikacji, w tym wyskakujących okienek i okien dialogowych.
winapp ui list-windows -a imageresizer
winapp ui list-windows -a Terminal
winapp ui list-windows # all windows (no filter)
Obsługa struktury
| Framework | Sprawdzić | wyszukać | wywołać | set-value | zrzut ekranu |
|---|---|---|---|---|---|
| WPF | ✅ Pełne drzewo | ✅ Wszystkie właściwości | ✅ Wszystkie wzorce | ✅ | ✅ |
| Windows Forms | ✅ | ✅ | ✅ | ✅ | ✅ |
| Win32 | ✅ | ✅ | ✅ | ✅ | ✅ |
| WinUI 3 | ✅ | ✅ | ✅ | ✅ | ✅ |
| Elektron | ⚠✔ Drzewo chromowe | ⚠✔ Ograniczone | ⚠✔ Różni się | ⚠✔ Różni się | ✅ |
| Flutter | ⚠✔ Podstawowa | ⚠✔ Podstawowa | ❌ Minimalne | ❌ | ✅ |
Troubleshooting
| Error | Przyczyna | Rozwiązanie |
|---|---|---|
| "Nie znaleziono uruchomionej aplikacji" | Aplikacja nie działa lub niezgodność nazw | Sprawdzanie nazwy procesu lub używanie identyfikatora PID |
| "Dopasowanie wielu okien" | Niejednoznaczna -a wartość |
Użyj -w <HWND> z wymienionych opcji |
| "ma wiele okien" | Proces ma wiele okien | Użyj -w <HWND> polecenia , aby kierować do określonego elementu |
| "Selektor pasował do N elementów" | Niejednoznaczny selektor starszej wersji | Użyj slugs z inspect danych wyjściowych lub dołącz [0]element , [1] do starszych selektorów |
| "Element mógł ulec zmianie" | Skrót Slug nie pasuje do bieżącego elementu |
inspect Uruchom ponownie lubsearch, aby uzyskać świeże ślimaki |
| "nie obsługuje żadnego wzorca wywołania" | Nie można wywołać elementu | Użyj inspect elementu w celu znalezienia elementu podrzędnego z możliwością wywołania |
| "Nie znaleziono okna UIA" | Interfejs użytkownika nie widzi procesu | Użyj list-windows polecenia , aby znaleźć HWND, a następnie -w |
| "Okno ma zerowy rozmiar" | Okno jest zminimalizowane | Aplikacja zostanie przywrócona automatycznie |
| Wyskakujące okienko/lista rozwijana nie są na zrzucie ekranu | Funkcja PrintWindow nie przechwytuje nakładek | Użyj --capture-screen flagi |
Typowe wzorce
Nawigowanie i weryfikowanie
winapp ui invoke btn-settings-a1b2 -a myapp # click a button
winapp ui wait-for pn-settingspage-c3d4 -a myapp # wait for page to load
winapp ui screenshot -a myapp --output settings.png # verify visually
Znajdowanie tekstu i wywoływanie jego elementu nadrzędnego
# Search shows invokable ancestor; invoke auto-walks to it
winapp ui invoke 'Save changes' -a myapp
# Or search first to see what matches, then invoke
winapp ui search "Save changes" -a myapp; winapp ui invoke btn-save-c3d4 -a myapp
Uściślanie zduplikowanych elementów
winapp ui search '#Image' -a myapp; winapp ui invoke itm-image-a2b3 -a myapp
Zrzut ekranu przedstawiający wyskakujące nakładki
winapp ui set-value txt-searchbox-e5f6 "query" -a myapp; winapp ui screenshot -a myapp --capture-screen
Nawigowanie, oczekiwanie i weryfikowanie (pojedynczy łańcuch)
winapp ui invoke btn-settings-a1b2 -a myapp; winapp ui wait-for pn-settingspage-c3d4 -a myapp --timeout 3000; winapp ui screenshot -a myapp -o settings.png
Odnajdywanie, klikanie i weryfikowanie
winapp ui inspect -a myapp --interactive; winapp ui invoke btn-submit-7a90 -a myapp; winapp ui screenshot -a myapp
Interakcja okna dialogowego pliku
Okna dialogowe otwierania/zapisywania plików to standardowe okna dialogowe Windows z obsługą interfejsu użytkownika:
# Trigger the dialog, find it, type the path, confirm
winapp ui invoke btn-openfilebtn-a2b3 -a myapp
winapp ui list-windows -a myapp # find dialog HWND
winapp ui set-value txt-1148-c4d5 "C:\path\to\file.png" -w <dialog-hwnd>
winapp ui invoke btn-open-e6f7 -w <dialog-hwnd>
Użyj inspect -w <dialog-hwnd> --interactive polecenia , aby odnaleźć rzeczywiste ślimaki dla określonego okna dialogowego.
Dlaczego ; łańcuch (nie &&)
Operator programu PowerShell może blokować się, gdy natywny && interfejs wiersza polecenia zapisuje w programie stderr lub używa sekwencji ucieczki ANSI. Zamiast tego — ; uruchamia każde polecenie bezwarunkowo i unika tego zakleszczenia. Jest to również lepsze w przypadku przepływów pracy agenta: zwykle chcesz, aby zrzut ekranu był uruchamiany nawet wtedy, gdy wywołanie miało wyjście niezerowe.
Wzorce testowania ciągłej integracji
Użyj winapp ui poleceń w potokach ciągłej integracji (GitHub Actions, Azure DevOps) na potrzeby testów weryfikacyjnych kompilacji i weryfikacji interfejsu użytkownika.
wait-for z --property i --value działa jako asercja — zwraca kod zakończenia 1 w przypadku przekroczenia limitu czasu, co powoduje automatyczne niepowodzenie kroku ciągłej integracji.
Uruchamianie i testowanie w GitHub Actions
steps:
- name: Build
run: dotnet build MyApp.csproj -c Debug -p:Platform=x64
- name: Launch and test
run: |
$result = winapp run .\bin\x64\Debug\net8.0-windows10.0.26100.0\win-x64 --detach --json | ConvertFrom-Json
$appPid = $result.ProcessId
# Wait for window to initialize
winapp ui wait-for "Main Window" -a $appPid --timeout 30000
# Run tests — each wait-for exits non-zero on failure
winapp ui invoke "Login" -a $appPid
winapp ui wait-for "Dashboard" -a $appPid --timeout 10000
winapp ui screenshot -a $appPid -o dashboard.png
Stan elementu assert z wait-for
wait-for --value sonduje, dopóki wartość elementu nie pasuje do oczekiwanego ciągu, używając tego samego inteligentnego rezerwowego co get-value (TextPattern → ValuePattern → SelectionPattern → Name). Zwraca kod zakończenia 0 zgodny, kod zakończenia 1 w przypadku przekroczenia limitu czasu — co czyni go asercją przyjazną dla ciągłej integracji. Zamiast tego użyj polecenia --property , aby sprawdzić określoną właściwość UIA.
# Assert: button click updated the counter (smart value fallback — works for TextBlock, TextBox, etc.)
winapp ui invoke "Counter Button" -a $pid
winapp ui wait-for "Counter Display" -a $pid --value "Count: 1" -t 5000
# Assert: text input was accepted
winapp ui set-value "Search Box" "hello world" -a $pid
winapp ui wait-for "Search Box" -a $pid --value "hello world" -t 3000
# Assert: checkbox was toggled (use --property for specific UIA properties)
winapp ui invoke "Dark Mode" -a $pid
winapp ui wait-for "Dark Mode" -a $pid --property ToggleState --value "On" -t 3000
# Assert: navigation happened (new page appeared)
winapp ui invoke "Settings" -a $pid
winapp ui wait-for "Settings Page" -a $pid -t 10000
# Assert: dialog was dismissed (element disappeared)
winapp ui invoke "Close" -a $pid
winapp ui wait-for "Dialog Title" -a $pid --gone -t 5000
Potwierdzanie przy użyciu danych wyjściowych JSON
Używanie z --json programem PowerShell lub jq w celu uzyskania bardziej złożonych asercji:
Kontrakt zakończenia kodu dla
searchiwait-forw--jsontrybie: gdy żaden element nie pasuje (search) lub limit czasu oczekiwania (wait-for), polecenie zapisuje w pełni analizowalne koperty wyniku do stdout ({ "matchCount": 0, ... }lub{ "found": false, "timedOut": true, ... }) i zwraca kod zakończenia 1. Stderr jest pusty w--jsontrybie (dane wyjściowe rejestratora są pomijane). Rozgałęzij na polach koperty lub na$LASTEXITCODE, w zależności od tego, co jest bardziej ergonomiczne.
# Assert: search found exactly one match
$result = winapp ui search "Submit" -a $pid --json | ConvertFrom-Json
if ($result.matchCount -ne 1) { throw "Expected 1 Submit button, found $($result.matchCount)" }
# Assert: element has expected properties
# inspect --json returns { windows: [{ hwnd, title, elements: [...] }] };
# each window's elements[] is the nested tree (children rendered via .children).
$tree = winapp ui inspect "Counter Display" -a $pid --json | ConvertFrom-Json
$counter = $tree.windows[0].elements[0]
if ($counter.name -ne "Count: 3") { throw "Counter value wrong: $($counter.name)" }
Przykład pełnego testu weryfikacyjnego kompilacji
# Launch
$app = winapp run .\build-output --detach --json | ConvertFrom-Json
# Verify app loaded
winapp ui wait-for "Main Page" -a $app.ProcessId -t 30000
# Interact and assert
winapp ui invoke "Add Item" -a $app.ProcessId
winapp ui set-value "Item Name" "Test Item" -a $app.ProcessId
winapp ui invoke "Save" -a $app.ProcessId
winapp ui wait-for "Test Item" -a $app.ProcessId -t 5000 # assert item appeared in list
winapp ui wait-for "Save" -a $app.ProcessId --gone -t 3000 # assert save dialog closed
# Visual verification
winapp ui screenshot -a $app.ProcessId -o smoke-test.png