work in progress

This commit is contained in:
2026-01-16 12:43:06 +01:00
parent 77a9579025
commit c8ee7defe8
236 changed files with 11405 additions and 28 deletions

144
designer/test/README.md Normal file
View 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\)

View 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
View 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
View 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()

View 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
View 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
}
}

View 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()

View 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()

View 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

View 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()

View 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()

View 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)