Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 57 additions & 3 deletions .github/workflows/ahk-lint-format-compile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
lint:
runs-on: windows-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v4

- name: Install AutoHotkey v1.1 (Portable)
run: choco install autohotkey.portable --version=1.1.36.01 -y
Expand Down Expand Up @@ -83,8 +83,7 @@ jobs:
$syntaxErrors += $rel
}

# Format check
$content = Get-Content $_.FullName -Raw
# Format check (reuses $content already read above)
$problems = @()
if (($content -match "(?m)^\t") -and ($content -match "(?m)^ ")) { $problems += "mixed indent" }
if ($content -match "[ \t]+`r?`n") { $problems += "trailing space" }
Expand Down Expand Up @@ -112,3 +111,58 @@ jobs:
exit 1
}
shell: pwsh

- name: Run Tests
run: |
function Test-IsAhkV2Script {
param(
[Parameter(Mandatory = $true)]
[string]$Path
)

$header = Get-Content -Path $Path -TotalCount 20 -ErrorAction SilentlyContinue
return $header -match '^\s*#Requires\s+AutoHotkey\s+v2(\.0)?\b'
}

$ahkV2 = "$env:ProgramFiles\AutoHotkey\v2\AutoHotkey64.exe"
$searchRoots = @("tests", "ahk", "Lib") | Where-Object { Test-Path $_ }
$testFiles = @()

foreach ($root in $searchRoots) {
$testFiles += Get-ChildItem -Path $root -Recurse -Filter *.ahk -File |
Where-Object {
($_.Name -like "test_*" -or $_.Name -like "*_Test.ahk") -and
(Test-IsAhkV2Script -Path $_.FullName)
}
}

$failed = @()

Comment thread
Ven0m0 marked this conversation as resolved.
if (-not $testFiles) {
Write-Host "No AutoHotkey v2 test files found under tests/ or ahk/."
exit 0
}

foreach ($tf in $testFiles) {
$rel = $tf.FullName -replace [regex]::Escape("$(Get-Location)\"), ""
$proc = Start-Process -FilePath $ahkV2 -ArgumentList "`"$($tf.FullName)`"" -PassThru -NoNewWindow
if (!$proc.WaitForExit(30000)) {
$proc.Kill()
Write-Host "❌ $rel - timed out" -ForegroundColor Red
$failed += $rel
} elseif ($proc.ExitCode -ne 0) {
Write-Host "❌ $rel - exit $($proc.ExitCode)" -ForegroundColor Red
$failed += $rel
} else {
Write-Host "✓ $rel" -ForegroundColor Green
}
}

Write-Host "`nRan: $($testFiles.Count) | Failed: $($failed.Count)"

if ($failed) {
Write-Host "`nFailed tests:" -ForegroundColor Red
$failed | % { Write-Host " $_" }
exit 1
}
shell: pwsh
7 changes: 4 additions & 3 deletions .github/workflows/build-cached.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
build-release:
runs-on: windows-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v4

- name: Cache AutoHotkey and Ahk2Exe
uses: actions/cache@v5
Expand Down Expand Up @@ -44,7 +44,8 @@
Expand-Archive "$env:TEMP\Ahk2Exe.zip" -DestinationPath "C:\AutoHotkey-Portable\Compiler" -Force
$requiredFiles = @(
"C:\AutoHotkey-Portable\Compiler\Ahk2Exe.exe",
"C:\AutoHotkey-Portable\Compiler\AutoHotkeySC.bin"
"C:\AutoHotkey-Portable\Compiler\Unicode 32-bit.bin",
"C:\AutoHotkey-Portable\Compiler\Unicode 64-bit.bin"
)
$missingFiles = $requiredFiles | Where-Object { -not (Test-Path $_) }
if ($missingFiles) {
Expand Down Expand Up @@ -88,7 +89,7 @@
shell: pwsh

- name: Create Release
uses: softprops/action-gh-release@v3
uses: softprops/action-gh-release@v2

Check warning on line 92 in .github/workflows/build-cached.yml

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

.github/workflows/build-cached.yml#L92

An action sourced from a third-party repository on GitHub is not pinned to a full length commit SHA. Pinning an action to a full length commit SHA is currently the only way to use an action as an immutable release.
with:
files: release/*.exe
fail_on_unmatched_files: true
4 changes: 2 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
build-release:
runs-on: windows-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v4

- name: Install Scoop
shell: pwsh
Expand Down Expand Up @@ -89,7 +89,7 @@ jobs:
shell: pwsh

- name: Create Release
uses: softprops/action-gh-release@v3
uses: softprops/action-gh-release@v2
with:
files: release/*.exe
fail_on_unmatched_files: true
4 changes: 2 additions & 2 deletions .github/workflows/copilot-setup-steps.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ jobs:
copilot-setup-steps:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v4

- uses: actions/setup-node@v6
- uses: actions/setup-node@v4
with:
node-version: "24"

Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/powershell.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:
name: PSScriptAnalyzer
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v4

- name: Run PSScriptAnalyzer
uses: microsoft/psscriptanalyzer-action@7a0da25f33985767f15f93140306528900744195
Expand All @@ -44,6 +44,6 @@ jobs:

# Upload the SARIF file generated in the previous step
- name: Upload SARIF results file
uses: github/codeql-action/upload-sarif@v4
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: results.sarif
4 changes: 2 additions & 2 deletions Lib/v2/WindowManager.ahk
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

; WindowManager – borderless/fullscreen utilities

static STYLE_DECORATIONS := 0xEC0000 ; title/menu/frame/sysmodal combined
static STYLE_UNDECORATED := -0xEC0000
global STYLE_DECORATIONS := "+0xEC0000" ; title/menu/frame/sysmodal combined
global STYLE_UNDECORATED := "-0xEC0000"

ToggleFakeFullscreen(winTitle := "A", api := "") {
if !api
Expand Down
6 changes: 3 additions & 3 deletions ahk/Keys.ahk
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#Requires AutoHotkey v2.0
#SingleInstance Force
#Include ..\Lib\v2\AHK_Common.ahk

#Include %A_ScriptDir%\..\Lib\v2\AHK_Common.ahk
InitScript(true, false, true) ; UIA required, no admin, optimize

InitScript(true, false, true)
SetTitleMatchMode(3)
SetNumLockState("AlwaysOn")
SetCapsLockState("AlwaysOff")
Expand Down
22 changes: 11 additions & 11 deletions ahk/test_WindowManager.ahk
Original file line number Diff line number Diff line change
Expand Up @@ -55,22 +55,22 @@ TestToggleFakeFullscreen_MakeFullscreen() {
; Verify calls
if (mockApi.calls.Length != 3) {
FileOpen("*", "w `n").Write("Fail: Expected 3 calls, got " mockApi.calls.Length "`n")
return false
ExitApp(1)
}

if (mockApi.calls[1].method != "WinGetStyle") {
FileOpen("*", "w `n").Write("Fail: First call was not WinGetStyle`n")
return false
ExitApp(1)
}

if (mockApi.calls[2].method != "WinSetStyle") {
FileOpen("*", "w `n").Write("Fail: Second call was not WinSetStyle`n")
return false
ExitApp(1)
}

if (mockApi.calls[3].method != "WinMove") {
FileOpen("*", "w `n").Write("Fail: Third call was not WinMove`n")
return false
ExitApp(1)
}

FileOpen("*", "w `n").Write("Pass: MakeFullscreen`n")
Expand All @@ -86,17 +86,17 @@ TestToggleFakeFullscreen_RestoreWindow() {
; Verify calls
if (mockApi.calls.Length != 3) {
FileOpen("*", "w `n").Write("Fail: Expected 3 calls, got " mockApi.calls.Length "`n")
return false
ExitApp(1)
}

if (mockApi.calls[2].method != "WinSetStyle") {
FileOpen("*", "w `n").Write("Fail: Second call was not WinSetStyle`n")
return false
ExitApp(1)
}

if (mockApi.calls[3].method != "WinRestore") {
FileOpen("*", "w `n").Write("Fail: Third call was not WinRestore`n")
return false
ExitApp(1)
}

FileOpen("*", "w `n").Write("Pass: RestoreWindow`n")
Expand All @@ -112,7 +112,7 @@ TestGetMonitorAtPos_InsideMonitor() {
res := GetMonitorAtPos(500, 500, mockApi)
if (res != 1) {
FileOpen("*", "w `n").Write("Fail: Expected 1, got " res "`n")
return false
ExitApp(1)
}
FileOpen("*", "w `n").Write("Pass: GetMonitorAtPos_InsideMonitor`n")
return true
Expand All @@ -127,7 +127,7 @@ TestGetMonitorAtPos_OutsideMonitors() {
res := GetMonitorAtPos(-100, 500, mockApi)
if (res != -1) {
FileOpen("*", "w `n").Write("Fail: Expected -1, got " res "`n")
return false
ExitApp(1)
}
FileOpen("*", "w `n").Write("Pass: GetMonitorAtPos_OutsideMonitors`n")
return true
Expand All @@ -143,7 +143,7 @@ TestGetMonitorAtPos_MultipleMonitors() {
res := GetMonitorAtPos(-500, 500, mockApi)
if (res != 2) {
FileOpen("*", "w `n").Write("Fail: Expected 2, got " res "`n")
return false
ExitApp(1)
}
FileOpen("*", "w `n").Write("Pass: GetMonitorAtPos_MultipleMonitors`n")
return true
Expand All @@ -157,4 +157,4 @@ TestGetMonitorAtPos_OutsideMonitors()
TestGetMonitorAtPos_MultipleMonitors()

FileOpen("*", "w `n").Write("All tests complete.`n")
ExitApp
ExitApp(0)
Loading