work in progress
This commit is contained in:
144
designer/test/README.md
Normal file
144
designer/test/README.md
Normal file
@@ -0,0 +1,144 @@
|
||||
# Mosis Designer UI Testing with AutoHotkey
|
||||
|
||||
## Overview
|
||||
|
||||
This folder contains AutoHotkey v2 scripts for automated UI testing of the Mosis Designer.
|
||||
|
||||
## Testing Architecture
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Test Runner (run_tests.ahk) │
|
||||
│ - Launches designer process │
|
||||
│ - Captures stdout for verification │
|
||||
│ - Runs test scripts sequentially │
|
||||
│ - Generates test report │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Test Scripts (test_*.ahk) │
|
||||
│ - test_navigation.ahk: Click apps, verify screen change │
|
||||
│ - test_back_button.ahk: Navigate and go back │
|
||||
│ - test_home_button.ahk: Navigate deep, press home │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Utilities (lib/utils.ahk) │
|
||||
│ - FindDesignerWindow(): Get window handle │
|
||||
│ - ClickPhone(x, y): Click at phone coordinates │
|
||||
│ - WaitForScreen(name): Wait for navigation log │
|
||||
│ - CaptureScreenshot(path): Save window image │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Window Identification
|
||||
|
||||
- **Window Title**: "Mosis Designer"
|
||||
- **Window Class**: GLFW window class (varies by version)
|
||||
- **Size**: 540x960 client area (phone resolution)
|
||||
|
||||
## Coordinate System
|
||||
|
||||
The phone UI uses a 540x960 coordinate system. AHK needs to:
|
||||
|
||||
1. Find the designer window
|
||||
2. Get the client area position
|
||||
3. Convert phone coordinates to screen coordinates
|
||||
|
||||
```
|
||||
Phone Coordinates (0,0 to 540,960)
|
||||
│
|
||||
▼
|
||||
┌──────────────────┐
|
||||
│ Window Title │ ← Window decorations
|
||||
├──────────────────┤
|
||||
│ │
|
||||
│ Phone UI │ ← Client area (540x960)
|
||||
│ (0,0) │
|
||||
│ ┌──────┐ │
|
||||
│ │ App │ │ ← Click target
|
||||
│ │ Icon │ │
|
||||
│ └──────┘ │
|
||||
│ │
|
||||
│ (540,960)
|
||||
└──────────────────┘
|
||||
```
|
||||
|
||||
## App Icon Positions (Home Screen)
|
||||
|
||||
Based on the home.rml layout with 4 columns:
|
||||
|
||||
| Row | App | Approx X | Approx Y |
|
||||
|-----|-----------|----------|----------|
|
||||
| 1 | Phone | 67 | 100 |
|
||||
| 1 | Messages | 202 | 100 |
|
||||
| 1 | Contacts | 337 | 100 |
|
||||
| 1 | Browser | 472 | 100 |
|
||||
| 2 | Gallery | 67 | 200 |
|
||||
| 2 | Camera | 202 | 200 |
|
||||
| 2 | Settings | 337 | 200 |
|
||||
| 2 | Music | 472 | 200 |
|
||||
|
||||
Dock items at bottom (~900 Y):
|
||||
- Phone: 67
|
||||
- Messages: 202
|
||||
- Contacts: 337
|
||||
- Browser: 472
|
||||
|
||||
## Verification Methods
|
||||
|
||||
### 1. Console Output Parsing
|
||||
The designer outputs navigation events to stdout:
|
||||
```
|
||||
navigateTo called with: dialer
|
||||
Loaded screen: apps/dialer/dialer.rml
|
||||
Navigated to: dialer (history depth: 1)
|
||||
goBack called (history depth: 1)
|
||||
Back to: home
|
||||
```
|
||||
|
||||
We can redirect stdout to a file and parse it for verification.
|
||||
|
||||
### 2. Screenshot Comparison
|
||||
Take screenshots at key points and compare with baselines.
|
||||
|
||||
### 3. Window Title Changes (future)
|
||||
Could modify designer to include current screen in title.
|
||||
|
||||
## Test Execution Flow
|
||||
|
||||
```
|
||||
1. Start designer with stdout redirected to log file
|
||||
2. Wait for window to appear
|
||||
3. Wait for "Document loaded successfully" in log
|
||||
4. Execute test actions (clicks, waits)
|
||||
5. Parse log for expected navigation events
|
||||
6. Report pass/fail
|
||||
7. Close designer
|
||||
```
|
||||
|
||||
## Files
|
||||
|
||||
- `lib/utils.ahk` - Shared utility functions
|
||||
- `run_tests.ahk` - Main test runner
|
||||
- `test_navigation.ahk` - Navigation test suite
|
||||
- `test_back_button.ahk` - Back button test suite
|
||||
- `config.ahk` - Test configuration (paths, timeouts)
|
||||
|
||||
## Usage
|
||||
|
||||
```powershell
|
||||
# Run all tests
|
||||
& "C:\Program Files\AutoHotkey\v2\AutoHotkey64.exe" run_tests.ahk
|
||||
|
||||
# Run specific test
|
||||
& "C:\Program Files\AutoHotkey\v2\AutoHotkey64.exe" test_navigation.ahk
|
||||
```
|
||||
|
||||
## Requirements
|
||||
|
||||
- AutoHotkey v2 (installed at C:\Program Files\AutoHotkey\v2)
|
||||
- Mosis Designer built (designer\build\Debug\mosis-designer.exe)
|
||||
- Test assets in place (src\main\assets\)
|
||||
102
designer/test/click_test.ahk
Normal file
102
designer/test/click_test.ahk
Normal file
@@ -0,0 +1,102 @@
|
||||
; Click test for Mosis Designer
|
||||
#Requires AutoHotkey v2.0
|
||||
|
||||
; Configuration
|
||||
WINDOW_TITLE := "Mosis Designer"
|
||||
PHONE_WIDTH := 540
|
||||
PHONE_HEIGHT := 960
|
||||
|
||||
; Output file
|
||||
outFile := A_ScriptDir . "\click_test_result.txt"
|
||||
if (FileExist(outFile))
|
||||
FileDelete(outFile)
|
||||
|
||||
Log(msg) {
|
||||
global outFile
|
||||
FileAppend(msg . "`n", outFile, "UTF-8")
|
||||
}
|
||||
|
||||
Log("=== Click Test ===")
|
||||
Log("Time: " . FormatTime(, "yyyy-MM-dd HH:mm:ss"))
|
||||
|
||||
; Find window
|
||||
hwnd := WinExist(WINDOW_TITLE)
|
||||
if (!hwnd) {
|
||||
Log("ERROR: Window not found")
|
||||
ExitApp(1)
|
||||
}
|
||||
|
||||
Log("Window found: " . hwnd)
|
||||
|
||||
; Get window info
|
||||
WinGetPos(&winX, &winY, &winW, &winH, hwnd)
|
||||
Log("Window position: X=" . winX . " Y=" . winY)
|
||||
Log("Window size: W=" . winW . " H=" . winH)
|
||||
|
||||
; Calculate DPI scale factor
|
||||
; Expected phone size is 540x960
|
||||
; Window has some decorations, estimate ~16 pixels width, ~40 height for title+borders
|
||||
expectedW := 540 + 16
|
||||
expectedH := 960 + 40
|
||||
scaleX := winW / expectedW
|
||||
scaleY := winH / expectedH
|
||||
Log("Estimated scale X: " . scaleX . " Y: " . scaleY)
|
||||
|
||||
; Use average scale (should be similar for both)
|
||||
scale := (scaleX + scaleY) / 2
|
||||
Log("Using scale factor: " . scale)
|
||||
|
||||
; Calculate client area offset (estimate title bar and borders scaled)
|
||||
titleBarHeight := Round(31 * scale)
|
||||
borderWidth := Round(8 * scale)
|
||||
Log("Estimated title bar: " . titleBarHeight . "px, border: " . borderWidth . "px")
|
||||
|
||||
; Client area start
|
||||
clientX := winX + borderWidth
|
||||
clientY := winY + titleBarHeight
|
||||
Log("Client area start: X=" . clientX . " Y=" . clientY)
|
||||
|
||||
; Function to convert phone coords to screen coords
|
||||
PhoneToScreen(phoneX, phoneY) {
|
||||
global clientX, clientY, scale
|
||||
return {
|
||||
x: Round(clientX + phoneX * scale),
|
||||
y: Round(clientY + phoneY * scale)
|
||||
}
|
||||
}
|
||||
|
||||
; Activate window
|
||||
WinActivate(hwnd)
|
||||
Sleep(200)
|
||||
|
||||
Log("")
|
||||
Log("=== Performing Click Test ===")
|
||||
|
||||
; Click on Phone app icon (first app in grid)
|
||||
; Position from home.rml layout: approximately (67, 120) in phone coords
|
||||
phonePos := PhoneToScreen(67, 120)
|
||||
Log("Phone app: phone(67,120) -> screen(" . phonePos.x . "," . phonePos.y . ")")
|
||||
|
||||
; Perform click
|
||||
Click(phonePos.x, phonePos.y)
|
||||
Log("Click sent!")
|
||||
|
||||
Sleep(1000)
|
||||
Log("Test complete - check if screen changed to Dialer")
|
||||
|
||||
; Also try clicking messages in dock for comparison
|
||||
Log("")
|
||||
Log("=== Second Click Test (Messages Dock) ===")
|
||||
; Dock is at bottom, approximately y=920 in phone coords
|
||||
; Messages is second item, approximately x=202
|
||||
msgPos := PhoneToScreen(202, 920)
|
||||
Log("Messages dock: phone(202,920) -> screen(" . msgPos.x . "," . msgPos.y . ")")
|
||||
|
||||
Click(msgPos.x, msgPos.y)
|
||||
Log("Click sent!")
|
||||
|
||||
Sleep(500)
|
||||
Log("")
|
||||
Log("=== Test Complete ===")
|
||||
|
||||
ExitApp(0)
|
||||
45
designer/test/config.ahk
Normal file
45
designer/test/config.ahk
Normal file
@@ -0,0 +1,45 @@
|
||||
; Mosis Designer Test Configuration
|
||||
; AutoHotkey v2
|
||||
|
||||
; Paths
|
||||
global DESIGNER_EXE := A_ScriptDir . "\..\build\Debug\mosis-designer.exe"
|
||||
global ASSETS_PATH := A_ScriptDir . "\..\..\src\main\assets"
|
||||
global HOME_RML := ASSETS_PATH . "\apps\home\home.rml"
|
||||
global LOG_FILE := A_ScriptDir . "\test_output.log"
|
||||
global SCREENSHOT_DIR := A_ScriptDir . "\screenshots"
|
||||
|
||||
; Window settings
|
||||
global WINDOW_TITLE := "Mosis Designer"
|
||||
global PHONE_WIDTH := 540
|
||||
global PHONE_HEIGHT := 960
|
||||
|
||||
; Timeouts (milliseconds)
|
||||
global STARTUP_TIMEOUT := 10000 ; Wait for window to appear
|
||||
global NAVIGATION_TIMEOUT := 2000 ; Wait for navigation to complete
|
||||
global CLICK_DELAY := 100 ; Delay after click
|
||||
|
||||
; App icon positions on home screen (approximate center of each icon)
|
||||
; Grid is 4 columns, icons are ~135px apart horizontally
|
||||
; First row starts around Y=100
|
||||
global APP_POSITIONS := Map(
|
||||
"phone", {x: 67, y: 120},
|
||||
"messages", {x: 202, y: 120},
|
||||
"contacts", {x: 337, y: 120},
|
||||
"browser", {x: 472, y: 120},
|
||||
"gallery", {x: 67, y: 220},
|
||||
"camera", {x: 202, y: 220},
|
||||
"settings", {x: 337, y: 220},
|
||||
"music", {x: 472, y: 220},
|
||||
"calendar", {x: 67, y: 320},
|
||||
"clock", {x: 202, y: 320},
|
||||
"notes", {x: 337, y: 320},
|
||||
"maps", {x: 472, y: 320}
|
||||
)
|
||||
|
||||
; Dock positions (bottom of screen)
|
||||
global DOCK_POSITIONS := Map(
|
||||
"phone", {x: 67, y: 920},
|
||||
"messages", {x: 202, y: 920},
|
||||
"contacts", {x: 337, y: 920},
|
||||
"browser", {x: 472, y: 920}
|
||||
)
|
||||
124
designer/test/diagnose.ahk
Normal file
124
designer/test/diagnose.ahk
Normal file
@@ -0,0 +1,124 @@
|
||||
; Mosis Designer Diagnostic Script
|
||||
; AutoHotkey v2
|
||||
; Outputs window information without user interaction
|
||||
|
||||
#Requires AutoHotkey v2.0
|
||||
|
||||
; Simple config (inline to avoid include issues)
|
||||
WINDOW_TITLE := "Mosis Designer"
|
||||
PHONE_WIDTH := 540
|
||||
PHONE_HEIGHT := 960
|
||||
|
||||
; Output file
|
||||
outputFile := A_ScriptDir . "\diagnose_output.txt"
|
||||
|
||||
; Clear previous output
|
||||
if (FileExist(outputFile))
|
||||
FileDelete(outputFile)
|
||||
|
||||
; Helper to write output
|
||||
WriteOutput(msg) {
|
||||
FileAppend(msg . "`n", outputFile)
|
||||
}
|
||||
|
||||
WriteOutput("=== Mosis Designer Diagnostic ===")
|
||||
WriteOutput("Time: " . A_Now)
|
||||
WriteOutput("")
|
||||
|
||||
; Find window
|
||||
hwnd := WinExist(WINDOW_TITLE)
|
||||
|
||||
if (!hwnd) {
|
||||
WriteOutput("ERROR: Window '" . WINDOW_TITLE . "' not found")
|
||||
WriteOutput("")
|
||||
WriteOutput("Looking for any GLFW windows...")
|
||||
|
||||
; Try to find any GLFW window
|
||||
windows := WinGetList()
|
||||
for wnd in windows {
|
||||
title := WinGetTitle(wnd)
|
||||
class := WinGetClass(wnd)
|
||||
if (InStr(class, "GLFW") || InStr(title, "Mosis") || InStr(title, "Designer")) {
|
||||
WriteOutput("Found candidate: " . wnd . " - Title: " . title . " - Class: " . class)
|
||||
}
|
||||
}
|
||||
ExitApp()
|
||||
}
|
||||
|
||||
WriteOutput("Window found!")
|
||||
WriteOutput("HWND: " . hwnd)
|
||||
|
||||
; Get window info
|
||||
title := WinGetTitle(hwnd)
|
||||
class := WinGetClass(hwnd)
|
||||
WinGetPos(&winX, &winY, &winW, &winH, hwnd)
|
||||
|
||||
WriteOutput("Title: " . title)
|
||||
WriteOutput("Class: " . class)
|
||||
WriteOutput("Position: X=" . winX . " Y=" . winY)
|
||||
WriteOutput("Size: W=" . winW . " H=" . winH)
|
||||
|
||||
; Estimate client area
|
||||
; For GLFW windows, borders are typically small
|
||||
; Let's try different estimates
|
||||
|
||||
WriteOutput("")
|
||||
WriteOutput("=== Client Area Estimates ===")
|
||||
|
||||
; Method 1: Standard Windows decorations
|
||||
borderW := 8
|
||||
titleH := 31
|
||||
clientX1 := winX + borderW
|
||||
clientY1 := winY + titleH
|
||||
WriteOutput("Estimate 1 (standard border): X=" . clientX1 . " Y=" . clientY1)
|
||||
|
||||
; Method 2: Minimal border (GLFW often uses this)
|
||||
borderW2 := 1
|
||||
titleH2 := 1
|
||||
clientX2 := winX + borderW2
|
||||
clientY2 := winY + titleH2
|
||||
WriteOutput("Estimate 2 (minimal border): X=" . clientX2 . " Y=" . clientY2)
|
||||
|
||||
; Method 3: No border (borderless window)
|
||||
WriteOutput("Estimate 3 (no border): X=" . winX . " Y=" . winY)
|
||||
|
||||
; Calculate expected phone area size vs actual window
|
||||
WriteOutput("")
|
||||
WriteOutput("=== Size Analysis ===")
|
||||
WriteOutput("Expected phone size: " . PHONE_WIDTH . "x" . PHONE_HEIGHT)
|
||||
WriteOutput("Actual window size: " . winW . "x" . winH)
|
||||
|
||||
expectedW := PHONE_WIDTH + (2 * 8) ; borders
|
||||
expectedH := PHONE_HEIGHT + 31 + 8 ; title + border
|
||||
WriteOutput("Expected window size (with decorations): " . expectedW . "x" . expectedH)
|
||||
|
||||
; Check if window is maximized or has different size
|
||||
if (winW > PHONE_WIDTH + 50 || winH > PHONE_HEIGHT + 100) {
|
||||
WriteOutput("WARNING: Window seems larger than expected - may be scaled or maximized")
|
||||
}
|
||||
|
||||
; Try a click test (won't do anything without activation, but log coordinates)
|
||||
WriteOutput("")
|
||||
WriteOutput("=== Click Coordinate Test ===")
|
||||
|
||||
; Phone center
|
||||
phoneX := 270
|
||||
phoneY := 480
|
||||
|
||||
; Convert to screen (using estimate 1)
|
||||
screenX := clientX1 + phoneX
|
||||
screenY := clientY1 + phoneY
|
||||
WriteOutput("Phone center (270, 480) -> Screen (" . screenX . ", " . screenY . ")")
|
||||
|
||||
; Phone app icon position
|
||||
phoneAppX := 67
|
||||
phoneAppY := 120
|
||||
screenAppX := clientX1 + phoneAppX
|
||||
screenAppY := clientY1 + phoneAppY
|
||||
WriteOutput("Phone app icon (67, 120) -> Screen (" . screenAppX . ", " . screenAppY . ")")
|
||||
|
||||
WriteOutput("")
|
||||
WriteOutput("=== Diagnostic Complete ===")
|
||||
WriteOutput("Output written to: " . outputFile)
|
||||
|
||||
ExitApp()
|
||||
149
designer/test/full_click_test.ahk
Normal file
149
designer/test/full_click_test.ahk
Normal file
@@ -0,0 +1,149 @@
|
||||
; Full click test with output verification
|
||||
#Requires AutoHotkey v2.0
|
||||
|
||||
; Configuration
|
||||
DESIGNER_EXE := A_ScriptDir . "\..\build\Debug\mosis-designer.exe"
|
||||
HOME_RML := A_ScriptDir . "\..\..\src\main\assets\apps\home\home.rml"
|
||||
WINDOW_TITLE := "Mosis Designer"
|
||||
PHONE_WIDTH := 540
|
||||
PHONE_HEIGHT := 960
|
||||
|
||||
; Output files
|
||||
logFile := A_ScriptDir . "\designer_output.log"
|
||||
resultFile := A_ScriptDir . "\full_test_result.txt"
|
||||
|
||||
if (FileExist(logFile))
|
||||
FileDelete(logFile)
|
||||
if (FileExist(resultFile))
|
||||
FileDelete(resultFile)
|
||||
|
||||
Log(msg) {
|
||||
global resultFile
|
||||
FileAppend(msg . "`n", resultFile, "UTF-8")
|
||||
}
|
||||
|
||||
Log("=== Full Click Test with Output Capture ===")
|
||||
Log("Time: " . FormatTime(, "yyyy-MM-dd HH:mm:ss"))
|
||||
Log("")
|
||||
|
||||
; Start designer with output redirection
|
||||
Log("Starting designer...")
|
||||
cmd := '"' . DESIGNER_EXE . '" "' . HOME_RML . '" > "' . logFile . '" 2>&1'
|
||||
Log("Command: " . cmd)
|
||||
|
||||
; Run via cmd to handle redirection
|
||||
Run(A_ComSpec . " /c " . cmd, A_ScriptDir, , &pid)
|
||||
Log("Started with PID: " . pid)
|
||||
|
||||
; Wait for window
|
||||
Log("Waiting for window...")
|
||||
startTime := A_TickCount
|
||||
hwnd := 0
|
||||
while (A_TickCount - startTime < 15000) {
|
||||
hwnd := WinExist(WINDOW_TITLE)
|
||||
if (hwnd)
|
||||
break
|
||||
Sleep(200)
|
||||
}
|
||||
|
||||
if (!hwnd) {
|
||||
Log("ERROR: Window did not appear within 15 seconds")
|
||||
ExitApp(1)
|
||||
}
|
||||
Log("Window appeared: " . hwnd)
|
||||
|
||||
; Wait for document to load
|
||||
Sleep(2000)
|
||||
|
||||
; Get window dimensions and calculate scale
|
||||
WinGetPos(&winX, &winY, &winW, &winH, hwnd)
|
||||
Log("Window: X=" . winX . " Y=" . winY . " W=" . winW . " H=" . winH)
|
||||
|
||||
; Calculate scale
|
||||
expectedW := 540 + 16
|
||||
expectedH := 960 + 40
|
||||
scale := (winW / expectedW + winH / expectedH) / 2
|
||||
Log("DPI Scale: " . scale)
|
||||
|
||||
; Calculate client offset
|
||||
titleBar := Round(31 * scale)
|
||||
border := Round(8 * scale)
|
||||
clientX := winX + border
|
||||
clientY := winY + titleBar
|
||||
Log("Client: X=" . clientX . " Y=" . clientY)
|
||||
|
||||
; Activate window
|
||||
WinActivate(hwnd)
|
||||
Sleep(300)
|
||||
|
||||
; Function to click at phone coordinates
|
||||
ClickAt(phoneX, phoneY, desc) {
|
||||
global clientX, clientY, scale, hwnd
|
||||
screenX := Round(clientX + phoneX * scale)
|
||||
screenY := Round(clientY + phoneY * scale)
|
||||
Log("Click " . desc . ": phone(" . phoneX . "," . phoneY . ") -> screen(" . screenX . "," . screenY . ")")
|
||||
|
||||
; Activate and click
|
||||
WinActivate(hwnd)
|
||||
Sleep(50)
|
||||
Click(screenX, screenY)
|
||||
Sleep(500)
|
||||
}
|
||||
|
||||
Log("")
|
||||
Log("=== Test 1: Click Phone App ===")
|
||||
ClickAt(67, 120, "Phone app")
|
||||
Sleep(1500)
|
||||
|
||||
; Check log for navigation
|
||||
Log("Checking log for navigation...")
|
||||
if (FileExist(logFile)) {
|
||||
content := FileRead(logFile)
|
||||
if (InStr(content, "Navigated to: dialer") || InStr(content, "Loaded screen: apps/dialer")) {
|
||||
Log("SUCCESS: Navigation to dialer detected!")
|
||||
} else if (InStr(content, "navigateTo called")) {
|
||||
Log("PARTIAL: navigateTo was called but navigation may have failed")
|
||||
} else {
|
||||
Log("FAIL: No navigation detected")
|
||||
}
|
||||
} else {
|
||||
Log("WARNING: Log file not found")
|
||||
}
|
||||
|
||||
Log("")
|
||||
Log("=== Test 2: Click Messages Dock ===")
|
||||
ClickAt(202, 920, "Messages dock")
|
||||
Sleep(1500)
|
||||
|
||||
if (FileExist(logFile)) {
|
||||
content := FileRead(logFile)
|
||||
if (InStr(content, "messages")) {
|
||||
Log("SUCCESS: Messages-related activity detected")
|
||||
} else {
|
||||
Log("FAIL: No messages navigation detected")
|
||||
}
|
||||
}
|
||||
|
||||
Log("")
|
||||
Log("=== Cleaning Up ===")
|
||||
; Close designer
|
||||
WinClose(hwnd)
|
||||
Sleep(500)
|
||||
|
||||
; Dump the full log
|
||||
Log("")
|
||||
Log("=== Designer Log Contents ===")
|
||||
if (FileExist(logFile)) {
|
||||
content := FileRead(logFile)
|
||||
; Only show last part of log (navigation related)
|
||||
lines := StrSplit(content, "`n")
|
||||
Log("(Last 30 lines)")
|
||||
startIdx := lines.Length > 30 ? lines.Length - 30 : 1
|
||||
loop lines.Length - startIdx + 1 {
|
||||
Log(lines[startIdx + A_Index - 1])
|
||||
}
|
||||
}
|
||||
|
||||
Log("")
|
||||
Log("=== Test Complete ===")
|
||||
ExitApp(0)
|
||||
298
designer/test/lib/utils.ahk
Normal file
298
designer/test/lib/utils.ahk
Normal file
@@ -0,0 +1,298 @@
|
||||
; Mosis Designer Test Utilities
|
||||
; AutoHotkey v2
|
||||
|
||||
#Include "..\config.ahk"
|
||||
|
||||
; Find the designer window and return its handle
|
||||
FindDesignerWindow() {
|
||||
return WinExist(WINDOW_TITLE)
|
||||
}
|
||||
|
||||
; Wait for the designer window to appear
|
||||
; Returns window handle or 0 if timeout
|
||||
WaitForDesignerWindow(timeout := 0) {
|
||||
if (timeout = 0)
|
||||
timeout := STARTUP_TIMEOUT
|
||||
|
||||
startTime := A_TickCount
|
||||
while (A_TickCount - startTime < timeout) {
|
||||
hwnd := FindDesignerWindow()
|
||||
if (hwnd) {
|
||||
; Give window time to fully initialize
|
||||
Sleep(500)
|
||||
return hwnd
|
||||
}
|
||||
Sleep(100)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
; Get the client area position of the designer window
|
||||
; Returns {x, y, w, h} or 0 if window not found
|
||||
GetClientArea(hwnd := 0) {
|
||||
if (hwnd = 0)
|
||||
hwnd := FindDesignerWindow()
|
||||
if (!hwnd)
|
||||
return 0
|
||||
|
||||
; Get window position
|
||||
WinGetPos(&winX, &winY, &winW, &winH, hwnd)
|
||||
|
||||
; Get client area - for GLFW windows, typically minimal border
|
||||
; Client area starts after title bar
|
||||
; We'll estimate based on typical Windows decorations
|
||||
; Title bar is usually ~30-40 pixels, borders ~8 pixels each side
|
||||
|
||||
; For a more accurate approach, we could use DllCall to GetClientRect
|
||||
; But for GLFW windows, the client area often matches the requested size
|
||||
|
||||
; Calculate client area assuming standard decorations
|
||||
borderWidth := 8
|
||||
titleHeight := 31
|
||||
|
||||
return {
|
||||
x: winX + borderWidth,
|
||||
y: winY + titleHeight,
|
||||
w: PHONE_WIDTH,
|
||||
h: PHONE_HEIGHT
|
||||
}
|
||||
}
|
||||
|
||||
; Convert phone coordinates to screen coordinates
|
||||
PhoneToScreen(phoneX, phoneY, hwnd := 0) {
|
||||
client := GetClientArea(hwnd)
|
||||
if (!client)
|
||||
return 0
|
||||
|
||||
return {
|
||||
x: client.x + phoneX,
|
||||
y: client.y + phoneY
|
||||
}
|
||||
}
|
||||
|
||||
; Click at phone coordinates
|
||||
ClickPhone(phoneX, phoneY, hwnd := 0) {
|
||||
if (hwnd = 0)
|
||||
hwnd := FindDesignerWindow()
|
||||
if (!hwnd) {
|
||||
LogMessage("ERROR: Designer window not found")
|
||||
return false
|
||||
}
|
||||
|
||||
; Activate window first
|
||||
WinActivate(hwnd)
|
||||
Sleep(50)
|
||||
|
||||
screen := PhoneToScreen(phoneX, phoneY, hwnd)
|
||||
if (!screen) {
|
||||
LogMessage("ERROR: Could not convert coordinates")
|
||||
return false
|
||||
}
|
||||
|
||||
; Move and click
|
||||
Click(screen.x, screen.y)
|
||||
Sleep(CLICK_DELAY)
|
||||
|
||||
LogMessage("Clicked at phone(" . phoneX . "," . phoneY . ") -> screen(" . screen.x . "," . screen.y . ")")
|
||||
return true
|
||||
}
|
||||
|
||||
; Click on a named app icon
|
||||
ClickApp(appName, hwnd := 0) {
|
||||
if (!APP_POSITIONS.Has(appName)) {
|
||||
LogMessage("ERROR: Unknown app: " . appName)
|
||||
return false
|
||||
}
|
||||
|
||||
pos := APP_POSITIONS[appName]
|
||||
LogMessage("Clicking app: " . appName)
|
||||
return ClickPhone(pos.x, pos.y, hwnd)
|
||||
}
|
||||
|
||||
; Click on a dock item
|
||||
ClickDock(appName, hwnd := 0) {
|
||||
if (!DOCK_POSITIONS.Has(appName)) {
|
||||
LogMessage("ERROR: Unknown dock item: " . appName)
|
||||
return false
|
||||
}
|
||||
|
||||
pos := DOCK_POSITIONS[appName]
|
||||
LogMessage("Clicking dock: " . appName)
|
||||
return ClickPhone(pos.x, pos.y, hwnd)
|
||||
}
|
||||
|
||||
; Send keyboard input to the designer
|
||||
SendToDesigner(keys, hwnd := 0) {
|
||||
if (hwnd = 0)
|
||||
hwnd := FindDesignerWindow()
|
||||
if (!hwnd)
|
||||
return false
|
||||
|
||||
WinActivate(hwnd)
|
||||
Sleep(50)
|
||||
Send(keys)
|
||||
return true
|
||||
}
|
||||
|
||||
; Read the log file and check for a pattern
|
||||
; Returns the matching line or empty string
|
||||
CheckLogFor(pattern, logFile := 0) {
|
||||
if (logFile = 0)
|
||||
logFile := LOG_FILE
|
||||
|
||||
if (!FileExist(logFile))
|
||||
return ""
|
||||
|
||||
content := FileRead(logFile)
|
||||
lines := StrSplit(content, "`n")
|
||||
|
||||
; Search from end (most recent)
|
||||
loop lines.Length {
|
||||
idx := lines.Length - A_Index + 1
|
||||
line := lines[idx]
|
||||
if (InStr(line, pattern))
|
||||
return line
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
; Wait for a specific pattern to appear in the log
|
||||
WaitForLog(pattern, timeout := 0, logFile := 0) {
|
||||
if (timeout = 0)
|
||||
timeout := NAVIGATION_TIMEOUT
|
||||
if (logFile = 0)
|
||||
logFile := LOG_FILE
|
||||
|
||||
startTime := A_TickCount
|
||||
while (A_TickCount - startTime < timeout) {
|
||||
result := CheckLogFor(pattern, logFile)
|
||||
if (result)
|
||||
return result
|
||||
Sleep(100)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
; Wait for navigation to a specific screen
|
||||
WaitForNavigation(screenName, timeout := 0) {
|
||||
pattern := "Navigated to: " . screenName
|
||||
return WaitForLog(pattern, timeout)
|
||||
}
|
||||
|
||||
; Wait for back navigation
|
||||
WaitForBack(timeout := 0) {
|
||||
return WaitForLog("Back to:", timeout)
|
||||
}
|
||||
|
||||
; Take a screenshot of the designer window
|
||||
CaptureScreenshot(filename, hwnd := 0) {
|
||||
if (hwnd = 0)
|
||||
hwnd := FindDesignerWindow()
|
||||
if (!hwnd)
|
||||
return false
|
||||
|
||||
; Ensure screenshot directory exists
|
||||
if (!DirExist(SCREENSHOT_DIR))
|
||||
DirCreate(SCREENSHOT_DIR)
|
||||
|
||||
fullPath := SCREENSHOT_DIR . "\" . filename
|
||||
|
||||
; Use built-in screenshot capability
|
||||
; Note: This captures the entire window including decorations
|
||||
try {
|
||||
; Activate and bring to front
|
||||
WinActivate(hwnd)
|
||||
Sleep(100)
|
||||
|
||||
; Get window position
|
||||
WinGetPos(&x, &y, &w, &h, hwnd)
|
||||
|
||||
; Use GDI+ or Windows API for screenshot
|
||||
; For simplicity, we'll use the Snipping approach
|
||||
; In production, you'd use a proper GDI+ screenshot
|
||||
|
||||
LogMessage("Screenshot requested: " . fullPath . " (not implemented)")
|
||||
return false
|
||||
} catch as e {
|
||||
LogMessage("Screenshot error: " . e.Message)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
; Log a message with timestamp
|
||||
LogMessage(msg) {
|
||||
timestamp := FormatTime(, "yyyy-MM-dd HH:mm:ss")
|
||||
line := "[" . timestamp . "] " . msg . "`n"
|
||||
|
||||
; Write to console
|
||||
OutputDebug(line)
|
||||
|
||||
; Also append to a test log file
|
||||
testLog := A_ScriptDir . "\test_run.log"
|
||||
FileAppend(line, testLog)
|
||||
}
|
||||
|
||||
; Clear test logs
|
||||
ClearLogs() {
|
||||
testLog := A_ScriptDir . "\test_run.log"
|
||||
if (FileExist(testLog))
|
||||
FileDelete(testLog)
|
||||
if (FileExist(LOG_FILE))
|
||||
FileDelete(LOG_FILE)
|
||||
}
|
||||
|
||||
; Close the designer window
|
||||
CloseDesigner(hwnd := 0) {
|
||||
if (hwnd = 0)
|
||||
hwnd := FindDesignerWindow()
|
||||
if (hwnd) {
|
||||
WinClose(hwnd)
|
||||
Sleep(500)
|
||||
}
|
||||
}
|
||||
|
||||
; Kill any running designer processes
|
||||
KillDesigner() {
|
||||
try {
|
||||
Run('taskkill /F /IM mosis-designer.exe', , "Hide")
|
||||
}
|
||||
Sleep(500)
|
||||
}
|
||||
|
||||
; Start the designer process with log redirection
|
||||
; Returns the process ID or 0 on failure
|
||||
StartDesigner(rmlFile := 0) {
|
||||
if (rmlFile = 0)
|
||||
rmlFile := HOME_RML
|
||||
|
||||
; Build command with output redirection
|
||||
cmd := '"' . DESIGNER_EXE . '" "' . rmlFile . '"'
|
||||
|
||||
LogMessage("Starting designer: " . cmd)
|
||||
|
||||
; Start process and capture output
|
||||
; We'll redirect to a log file
|
||||
fullCmd := A_ComSpec . ' /c "' . cmd . '" > "' . LOG_FILE . '" 2>&1'
|
||||
|
||||
Run(fullCmd, A_ScriptDir, "Hide", &pid)
|
||||
|
||||
if (pid) {
|
||||
LogMessage("Designer started with PID: " . pid)
|
||||
return pid
|
||||
}
|
||||
|
||||
LogMessage("ERROR: Failed to start designer")
|
||||
return 0
|
||||
}
|
||||
|
||||
; Assert helper - logs pass/fail and returns result
|
||||
Assert(condition, testName) {
|
||||
if (condition) {
|
||||
LogMessage("PASS: " . testName)
|
||||
return true
|
||||
} else {
|
||||
LogMessage("FAIL: " . testName)
|
||||
return false
|
||||
}
|
||||
}
|
||||
65
designer/test/run_tests.ahk
Normal file
65
designer/test/run_tests.ahk
Normal file
@@ -0,0 +1,65 @@
|
||||
; Mosis Designer Test Runner
|
||||
; AutoHotkey v2
|
||||
; Runs all test scripts and generates a report
|
||||
|
||||
#Requires AutoHotkey v2.0
|
||||
#Include "lib\utils.ahk"
|
||||
|
||||
; Test scripts to run
|
||||
global testScripts := [
|
||||
"test_navigation.ahk"
|
||||
]
|
||||
|
||||
; Run all tests
|
||||
RunAllTests() {
|
||||
LogMessage("========================================")
|
||||
LogMessage("MOSIS DESIGNER TEST SUITE")
|
||||
LogMessage("========================================")
|
||||
|
||||
totalPassed := 0
|
||||
totalFailed := 0
|
||||
|
||||
; Clean up
|
||||
KillDesigner()
|
||||
ClearLogs()
|
||||
|
||||
for script in testScripts {
|
||||
LogMessage("")
|
||||
LogMessage("Running: " . script)
|
||||
LogMessage("----------------------------------------")
|
||||
|
||||
scriptPath := A_ScriptDir . "\" . script
|
||||
|
||||
if (!FileExist(scriptPath)) {
|
||||
LogMessage("ERROR: Script not found: " . scriptPath)
|
||||
totalFailed++
|
||||
continue
|
||||
}
|
||||
|
||||
; Run the test script
|
||||
try {
|
||||
ahkPath := "C:\Program Files\AutoHotkey\v2\AutoHotkey64.exe"
|
||||
RunWait('"' . ahkPath . '" "' . scriptPath . '"', A_ScriptDir)
|
||||
} catch as e {
|
||||
LogMessage("ERROR running script: " . e.Message)
|
||||
totalFailed++
|
||||
}
|
||||
|
||||
; Brief pause between tests
|
||||
Sleep(1000)
|
||||
}
|
||||
|
||||
; Final cleanup
|
||||
KillDesigner()
|
||||
|
||||
; Generate report
|
||||
LogMessage("")
|
||||
LogMessage("========================================")
|
||||
LogMessage("TEST SUITE COMPLETE")
|
||||
LogMessage("Check test_run.log for detailed results")
|
||||
LogMessage("========================================")
|
||||
}
|
||||
|
||||
; Main
|
||||
RunAllTests()
|
||||
ExitApp()
|
||||
21
designer/test/simple_test.ahk
Normal file
21
designer/test/simple_test.ahk
Normal file
@@ -0,0 +1,21 @@
|
||||
; Simple window finder test
|
||||
#Requires AutoHotkey v2.0
|
||||
|
||||
; Write to stdout (will show in console)
|
||||
OutputDebug("Starting simple test`n")
|
||||
|
||||
; Try to find the window
|
||||
hwnd := WinExist("Mosis Designer")
|
||||
|
||||
if (hwnd) {
|
||||
WinGetPos(&x, &y, &w, &h, hwnd)
|
||||
msg := "Found! X:" . x . " Y:" . y . " W:" . w . " H:" . h
|
||||
} else {
|
||||
msg := "Window not found"
|
||||
}
|
||||
|
||||
; Write result to a file
|
||||
outFile := A_ScriptDir . "\simple_result.txt"
|
||||
FileAppend(msg . "`n", outFile, "UTF-8")
|
||||
|
||||
ExitApp()
|
||||
110
designer/test/test_interactive.ahk
Normal file
110
designer/test/test_interactive.ahk
Normal file
@@ -0,0 +1,110 @@
|
||||
; Mosis Designer Interactive Test Helper
|
||||
; AutoHotkey v2
|
||||
; Launches designer and shows coordinates as you click
|
||||
|
||||
#Requires AutoHotkey v2.0
|
||||
#Include "lib\utils.ahk"
|
||||
|
||||
; Global state
|
||||
global isRunning := true
|
||||
global hwnd := 0
|
||||
|
||||
; Create a simple GUI to show status
|
||||
CreateStatusGui() {
|
||||
global statusGui, statusText, coordText
|
||||
|
||||
statusGui := Gui("+AlwaysOnTop", "Mosis Test Helper")
|
||||
statusGui.SetFont("s10")
|
||||
statusGui.Add("Text", "w300", "Designer Status:")
|
||||
statusText := statusGui.Add("Text", "w300 h20", "Not running")
|
||||
statusGui.Add("Text", "w300", "Mouse Position (Phone Coords):")
|
||||
coordText := statusGui.Add("Text", "w300 h20", "N/A")
|
||||
statusGui.Add("Text", "w300", "")
|
||||
statusGui.Add("Button", "w100", "Refresh").OnEvent("Click", RefreshStatus)
|
||||
statusGui.Add("Button", "x+10 w100", "Click Test").OnEvent("Click", DoClickTest)
|
||||
statusGui.Add("Button", "x+10 w80", "Exit").OnEvent("Click", (*) => ExitApp())
|
||||
|
||||
statusGui.OnEvent("Close", (*) => ExitApp())
|
||||
statusGui.Show("x10 y10")
|
||||
}
|
||||
|
||||
; Refresh status display
|
||||
RefreshStatus(*) {
|
||||
global hwnd, statusText
|
||||
|
||||
hwnd := FindDesignerWindow()
|
||||
if (hwnd) {
|
||||
statusText.Value := "Running (hwnd: " . hwnd . ")"
|
||||
} else {
|
||||
statusText.Value := "Not running"
|
||||
}
|
||||
}
|
||||
|
||||
; Perform a test click at center of phone
|
||||
DoClickTest(*) {
|
||||
global hwnd
|
||||
|
||||
hwnd := FindDesignerWindow()
|
||||
if (!hwnd) {
|
||||
MsgBox("Designer window not found!")
|
||||
return
|
||||
}
|
||||
|
||||
; Click center of phone
|
||||
ClickPhone(270, 480, hwnd)
|
||||
MsgBox("Clicked at phone center (270, 480)")
|
||||
}
|
||||
|
||||
; Update coordinate display based on mouse position
|
||||
UpdateCoordinates() {
|
||||
global hwnd, coordText
|
||||
|
||||
if (!hwnd) {
|
||||
hwnd := FindDesignerWindow()
|
||||
if (!hwnd) {
|
||||
coordText.Value := "Window not found"
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
; Get mouse position
|
||||
CoordMode("Mouse", "Screen")
|
||||
MouseGetPos(&mouseX, &mouseY)
|
||||
|
||||
; Get client area
|
||||
client := GetClientArea(hwnd)
|
||||
if (!client) {
|
||||
coordText.Value := "Could not get client area"
|
||||
return
|
||||
}
|
||||
|
||||
; Calculate phone coordinates
|
||||
phoneX := mouseX - client.x
|
||||
phoneY := mouseY - client.y
|
||||
|
||||
; Check if within phone bounds
|
||||
if (phoneX >= 0 && phoneX < PHONE_WIDTH && phoneY >= 0 && phoneY < PHONE_HEIGHT) {
|
||||
coordText.Value := "X: " . phoneX . " Y: " . phoneY
|
||||
} else {
|
||||
coordText.Value := "Outside phone area"
|
||||
}
|
||||
}
|
||||
|
||||
; Timer to update coordinates
|
||||
SetTimer(UpdateCoordinates, 100)
|
||||
|
||||
; Main
|
||||
LogMessage("Starting interactive test helper")
|
||||
|
||||
; Start designer if not running
|
||||
if (!FindDesignerWindow()) {
|
||||
LogMessage("Starting designer...")
|
||||
StartDesigner()
|
||||
Sleep(3000)
|
||||
}
|
||||
|
||||
CreateStatusGui()
|
||||
RefreshStatus()
|
||||
|
||||
; Keep running
|
||||
return
|
||||
77
designer/test/test_manual_clicks.ahk
Normal file
77
designer/test/test_manual_clicks.ahk
Normal file
@@ -0,0 +1,77 @@
|
||||
; Mosis Designer Manual Click Test
|
||||
; AutoHotkey v2
|
||||
; Tests clicking on specific app icons with an already-running designer
|
||||
|
||||
#Requires AutoHotkey v2.0
|
||||
#Include "lib\utils.ahk"
|
||||
|
||||
; Wait for designer to be running
|
||||
LogMessage("Looking for designer window...")
|
||||
LogMessage("Please start the designer manually if not running:")
|
||||
LogMessage(" cd designer && build\\Debug\\mosis-designer.exe ..\\src\\main\\assets\\apps\\home\\home.rml")
|
||||
|
||||
hwnd := WaitForDesignerWindow(30000) ; 30 second timeout
|
||||
|
||||
if (!hwnd) {
|
||||
MsgBox("Designer window not found after 30 seconds. Exiting.")
|
||||
ExitApp()
|
||||
}
|
||||
|
||||
LogMessage("Found designer window: " . hwnd)
|
||||
|
||||
; Get and display client area info
|
||||
client := GetClientArea(hwnd)
|
||||
if (client) {
|
||||
LogMessage("Client area: x=" . client.x . " y=" . client.y . " w=" . client.w . " h=" . client.h)
|
||||
}
|
||||
|
||||
; Interactive test loop
|
||||
MsgBox("Designer found! Click OK to start click tests.`n`nWe will click on the Phone app icon.")
|
||||
|
||||
; Test 1: Click Phone app
|
||||
LogMessage("Test 1: Clicking Phone app at (67, 120)")
|
||||
ClickPhone(67, 120, hwnd)
|
||||
Sleep(500)
|
||||
|
||||
result := MsgBox("Did the screen change to the Dialer?", "Verify", "YesNo")
|
||||
if (result = "Yes") {
|
||||
LogMessage("Test 1 PASSED: Phone app click worked")
|
||||
} else {
|
||||
LogMessage("Test 1 FAILED: Phone app click did not work")
|
||||
}
|
||||
|
||||
; Give user time to see result
|
||||
Sleep(1000)
|
||||
|
||||
; Test 2: Click Messages dock
|
||||
MsgBox("Now testing Messages dock item. Click OK to continue.")
|
||||
LogMessage("Test 2: Clicking Messages dock at (202, 920)")
|
||||
ClickPhone(202, 920, hwnd)
|
||||
Sleep(500)
|
||||
|
||||
result := MsgBox("Did the screen change to Messages?", "Verify", "YesNo")
|
||||
if (result = "Yes") {
|
||||
LogMessage("Test 2 PASSED: Messages dock click worked")
|
||||
} else {
|
||||
LogMessage("Test 2 FAILED: Messages dock click did not work")
|
||||
}
|
||||
|
||||
Sleep(1000)
|
||||
|
||||
; Test 3: Different coordinates for Messages (in case dock is higher)
|
||||
MsgBox("Testing alternative dock position. Click OK to continue.")
|
||||
LogMessage("Test 3: Clicking Messages at alternative position (202, 880)")
|
||||
ClickPhone(202, 880, hwnd)
|
||||
Sleep(500)
|
||||
|
||||
result := MsgBox("Did anything happen?", "Verify", "YesNo")
|
||||
if (result = "Yes") {
|
||||
LogMessage("Test 3: Alternative position worked better")
|
||||
} else {
|
||||
LogMessage("Test 3: Alternative position also failed")
|
||||
}
|
||||
|
||||
; Summary
|
||||
MsgBox("Tests complete! Check test_run.log for results.`n`nPath: " . A_ScriptDir . "\test_run.log")
|
||||
|
||||
ExitApp()
|
||||
194
designer/test/test_navigation.ahk
Normal file
194
designer/test/test_navigation.ahk
Normal file
@@ -0,0 +1,194 @@
|
||||
; Mosis Designer Navigation Test
|
||||
; AutoHotkey v2
|
||||
; Tests: Click on app icons and verify navigation occurs
|
||||
|
||||
#Requires AutoHotkey v2.0
|
||||
#Include "lib\utils.ahk"
|
||||
|
||||
; Test configuration
|
||||
testsPassed := 0
|
||||
testsFailed := 0
|
||||
|
||||
; Main test function
|
||||
RunNavigationTests() {
|
||||
global testsPassed, testsFailed
|
||||
|
||||
LogMessage("========================================")
|
||||
LogMessage("Starting Navigation Tests")
|
||||
LogMessage("========================================")
|
||||
|
||||
; Clean up any previous runs
|
||||
KillDesigner()
|
||||
ClearLogs()
|
||||
|
||||
; Start the designer
|
||||
pid := StartDesigner()
|
||||
if (!pid) {
|
||||
LogMessage("FATAL: Could not start designer")
|
||||
return false
|
||||
}
|
||||
|
||||
; Wait for window to appear
|
||||
LogMessage("Waiting for designer window...")
|
||||
hwnd := WaitForDesignerWindow()
|
||||
if (!hwnd) {
|
||||
LogMessage("FATAL: Designer window did not appear")
|
||||
KillDesigner()
|
||||
return false
|
||||
}
|
||||
LogMessage("Designer window found: " . hwnd)
|
||||
|
||||
; Wait for document to load
|
||||
Sleep(2000) ; Give time for initial document load
|
||||
|
||||
; Check log for successful load
|
||||
if (!WaitForLog("Document loaded successfully", 5000)) {
|
||||
LogMessage("WARNING: Did not detect document load confirmation")
|
||||
}
|
||||
|
||||
; Run individual tests
|
||||
TestClickDialer(hwnd)
|
||||
TestClickMessages(hwnd)
|
||||
TestClickContacts(hwnd)
|
||||
TestClickSettings(hwnd)
|
||||
|
||||
; Clean up
|
||||
LogMessage("Closing designer...")
|
||||
CloseDesigner(hwnd)
|
||||
Sleep(500)
|
||||
|
||||
; Report results
|
||||
LogMessage("========================================")
|
||||
LogMessage("Navigation Tests Complete")
|
||||
LogMessage("Passed: " . testsPassed)
|
||||
LogMessage("Failed: " . testsFailed)
|
||||
LogMessage("========================================")
|
||||
|
||||
return (testsFailed = 0)
|
||||
}
|
||||
|
||||
; Test: Click on Phone/Dialer app
|
||||
TestClickDialer(hwnd) {
|
||||
global testsPassed, testsFailed
|
||||
|
||||
LogMessage("--- Test: Click Dialer ---")
|
||||
|
||||
; First go home to ensure clean state
|
||||
; (In future, could send Home key)
|
||||
Sleep(500)
|
||||
|
||||
; Click the phone app
|
||||
if (!ClickApp("phone", hwnd)) {
|
||||
testsFailed++
|
||||
return
|
||||
}
|
||||
|
||||
Sleep(1000)
|
||||
|
||||
; Check log for navigation
|
||||
; Note: The log might say "dialer" because that's the screen name
|
||||
result := CheckLogFor("Navigated to: dialer")
|
||||
if (result) {
|
||||
LogMessage("Navigation confirmed: " . result)
|
||||
testsPassed++
|
||||
} else {
|
||||
; Also check if screen was loaded
|
||||
result := CheckLogFor("Loaded screen: apps/dialer")
|
||||
if (result) {
|
||||
LogMessage("Screen load confirmed: " . result)
|
||||
testsPassed++
|
||||
} else {
|
||||
LogMessage("Navigation not detected in log")
|
||||
testsFailed++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
; Test: Click on Messages app
|
||||
TestClickMessages(hwnd) {
|
||||
global testsPassed, testsFailed
|
||||
|
||||
LogMessage("--- Test: Click Messages ---")
|
||||
|
||||
; We're likely on dialer now, need to go back first
|
||||
; For now, just click messages dock item
|
||||
Sleep(500)
|
||||
|
||||
if (!ClickDock("messages", hwnd)) {
|
||||
testsFailed++
|
||||
return
|
||||
}
|
||||
|
||||
Sleep(1000)
|
||||
|
||||
result := CheckLogFor("Loaded screen: apps/messages")
|
||||
if (result) {
|
||||
LogMessage("Screen load confirmed: " . result)
|
||||
testsPassed++
|
||||
} else {
|
||||
LogMessage("Navigation not detected in log")
|
||||
testsFailed++
|
||||
}
|
||||
}
|
||||
|
||||
; Test: Click on Contacts app
|
||||
TestClickContacts(hwnd) {
|
||||
global testsPassed, testsFailed
|
||||
|
||||
LogMessage("--- Test: Click Contacts ---")
|
||||
Sleep(500)
|
||||
|
||||
if (!ClickDock("contacts", hwnd)) {
|
||||
testsFailed++
|
||||
return
|
||||
}
|
||||
|
||||
Sleep(1000)
|
||||
|
||||
result := CheckLogFor("Loaded screen: apps/contacts")
|
||||
if (result) {
|
||||
LogMessage("Screen load confirmed: " . result)
|
||||
testsPassed++
|
||||
} else {
|
||||
LogMessage("Navigation not detected in log")
|
||||
testsFailed++
|
||||
}
|
||||
}
|
||||
|
||||
; Test: Click on Settings app
|
||||
TestClickSettings(hwnd) {
|
||||
global testsPassed, testsFailed
|
||||
|
||||
LogMessage("--- Test: Click Settings ---")
|
||||
Sleep(500)
|
||||
|
||||
; Settings is on the main grid, not dock
|
||||
; But we're on contacts now, so we need to navigate
|
||||
; For this test, we'll just verify the click mechanics work
|
||||
|
||||
if (!ClickApp("settings", hwnd)) {
|
||||
; This will likely fail since we're not on home screen
|
||||
; But let's see what happens
|
||||
LogMessage("Click attempted (may fail if not on home)")
|
||||
testsFailed++
|
||||
return
|
||||
}
|
||||
|
||||
Sleep(1000)
|
||||
|
||||
result := CheckLogFor("Loaded screen: apps/settings")
|
||||
if (result) {
|
||||
LogMessage("Screen load confirmed: " . result)
|
||||
testsPassed++
|
||||
} else {
|
||||
LogMessage("Navigation not detected (expected if not on home screen)")
|
||||
testsFailed++
|
||||
}
|
||||
}
|
||||
|
||||
; Run the tests
|
||||
RunNavigationTests()
|
||||
|
||||
; Keep script alive briefly for logging
|
||||
Sleep(1000)
|
||||
ExitApp()
|
||||
124
designer/test/visual_click_test.ahk
Normal file
124
designer/test/visual_click_test.ahk
Normal file
@@ -0,0 +1,124 @@
|
||||
; Visual click test - verifies clicks by window interaction
|
||||
#Requires AutoHotkey v2.0
|
||||
|
||||
; Configuration
|
||||
DESIGNER_EXE := A_ScriptDir . "\..\build\Debug\mosis-designer.exe"
|
||||
HOME_RML := A_ScriptDir . "\..\..\src\main\assets\apps\home\home.rml"
|
||||
WINDOW_TITLE := "Mosis Designer"
|
||||
|
||||
resultFile := A_ScriptDir . "\visual_test_result.txt"
|
||||
if (FileExist(resultFile))
|
||||
FileDelete(resultFile)
|
||||
|
||||
Log(msg) {
|
||||
global resultFile
|
||||
FileAppend(msg . "`n", resultFile, "UTF-8")
|
||||
}
|
||||
|
||||
Log("=== Visual Click Test ===")
|
||||
Log("Time: " . FormatTime(, "yyyy-MM-dd HH:mm:ss"))
|
||||
|
||||
; Check if designer is running, if not start it
|
||||
hwnd := WinExist(WINDOW_TITLE)
|
||||
if (!hwnd) {
|
||||
Log("Starting designer...")
|
||||
Run(DESIGNER_EXE . ' "' . HOME_RML . '"', A_ScriptDir)
|
||||
|
||||
; Wait for window
|
||||
startTime := A_TickCount
|
||||
while (A_TickCount - startTime < 15000) {
|
||||
hwnd := WinExist(WINDOW_TITLE)
|
||||
if (hwnd)
|
||||
break
|
||||
Sleep(200)
|
||||
}
|
||||
|
||||
if (!hwnd) {
|
||||
Log("ERROR: Window did not appear")
|
||||
ExitApp(1)
|
||||
}
|
||||
Log("Designer started")
|
||||
Sleep(3000) ; Wait for full initialization
|
||||
} else {
|
||||
Log("Using existing designer window")
|
||||
}
|
||||
|
||||
Log("Window HWND: " . hwnd)
|
||||
|
||||
; Get window info
|
||||
WinGetPos(&winX, &winY, &winW, &winH, hwnd)
|
||||
Log("Window: " . winW . "x" . winH . " at (" . winX . "," . winY . ")")
|
||||
|
||||
; Calculate scale and client area
|
||||
scale := (winW / 556 + winH / 1000) / 2
|
||||
titleBar := Round(31 * scale)
|
||||
border := Round(8 * scale)
|
||||
clientX := winX + border
|
||||
clientY := winY + titleBar
|
||||
Log("Scale: " . scale . ", Client offset: (" . border . "," . titleBar . ")")
|
||||
|
||||
; Activate window
|
||||
WinActivate(hwnd)
|
||||
WinWaitActive(hwnd, , 3)
|
||||
Sleep(500)
|
||||
|
||||
Log("")
|
||||
Log("=== Click Sequence ===")
|
||||
|
||||
; Function to click
|
||||
DoClick(phoneX, phoneY, name) {
|
||||
global clientX, clientY, scale, hwnd
|
||||
|
||||
screenX := Round(clientX + phoneX * scale)
|
||||
screenY := Round(clientY + phoneY * scale)
|
||||
|
||||
Log("Clicking " . name . " at (" . phoneX . "," . phoneY . ") -> screen(" . screenX . "," . screenY . ")")
|
||||
|
||||
; Make sure window is active
|
||||
WinActivate(hwnd)
|
||||
Sleep(100)
|
||||
|
||||
; Move mouse first, then click
|
||||
MouseMove(screenX, screenY)
|
||||
Sleep(50)
|
||||
Click()
|
||||
Sleep(100)
|
||||
|
||||
Log("Click sent")
|
||||
}
|
||||
|
||||
; Test sequence:
|
||||
; 1. Click on Phone app (should navigate to dialer)
|
||||
Log("")
|
||||
Log("Step 1: Click Phone app icon")
|
||||
DoClick(67, 120, "Phone")
|
||||
Sleep(2000)
|
||||
|
||||
; 2. Click somewhere to go back (simulate back button or click home dock)
|
||||
Log("")
|
||||
Log("Step 2: Wait and observe...")
|
||||
Sleep(1000)
|
||||
|
||||
; 3. Click on Messages dock
|
||||
Log("")
|
||||
Log("Step 3: Click Messages dock")
|
||||
DoClick(202, 920, "Messages Dock")
|
||||
Sleep(2000)
|
||||
|
||||
; 4. Click on Contacts dock
|
||||
Log("")
|
||||
Log("Step 4: Click Contacts dock")
|
||||
DoClick(337, 920, "Contacts Dock")
|
||||
Sleep(2000)
|
||||
|
||||
Log("")
|
||||
Log("=== Test Sequence Complete ===")
|
||||
Log("Please verify visually that navigation occurred:")
|
||||
Log("- After Phone click: Should show Dialer screen")
|
||||
Log("- After Messages click: Should show Messages screen")
|
||||
Log("- After Contacts click: Should show Contacts screen")
|
||||
Log("")
|
||||
Log("Leaving designer running for manual inspection.")
|
||||
Log("Close it manually when done.")
|
||||
|
||||
ExitApp(0)
|
||||
Reference in New Issue
Block a user