work in progress
This commit is contained in:
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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user