com um clique
verify
Build, launch, and visually verify Perch's shelf UI from the CLI
Instalar com Codex ou Claude Copie este prompt, cole no Codex, Claude ou outro assistente e deixe que ele revise a página da skill e instale para você.
Menu
Build, launch, and visually verify Perch's shelf UI from the CLI
Instalar com Codex ou Claude Copie este prompt, cole no Codex, Claude ou outro assistente e deixe que ele revise a página da skill e instale para você.
Baseado na classificação ocupacional SOC
| name | verify |
| description | Build, launch, and visually verify Perch's shelf UI from the CLI |
swift build
PERCH_UITEST_ROOT=<scratch-dir>/perch-store PERCH_UITEST_HOVER=1 .build/debug/Perch > perch.log 2>&1 &
⚠️ A $HOME override does NOT isolate anything.
FileManager.url(for: .applicationSupportDirectory) and CFPreferences both
resolve the real home (getpwuid), ignoring $HOME — a test instance launched
that way seeds items straight into the user's REAL store
(~/Library/Application Support/Perch/). This happened once; four test items
had to be dug back out of the real index.json.
Isolate the store with a temporary env-guarded override at the top of
HoldingDirectory.standard() (remove before finishing):
if let testRoot = ProcessInfo.processInfo.environment["PERCH_UITEST_ROOT"] {
let holding = HoldingDirectory(root: URL(fileURLWithPath: testRoot, isDirectory: true))
try FileManager.default.createDirectory(at: holding.itemsDir, withIntermediateDirectories: true)
return holding
}
Confirm isolation before driving anything: the log must say "loaded 0 stored item(s)" and the seed must appear under the scratch store.
UserDefaults are ALWAYS the user's real ones — the test card renders with their actual theme (icons-only compact card is ~80pt wide), and anything the hook sets persists for the real app. Only set values that match theirs or are guarded by a changed-value check.
The user's production Perch is usually running from /Applications — never
kill it. Have the hook set arrivals.suppressed = true: the watched
Downloads/Desktop are the real ones, and a file landing mid-test would
otherwise add ghost rows that shift the measured geometry.
The debug build may pop a Sparkle "Unable to Check For Updates" window (~260×282); it's harmless — ignore it, don't confuse it for a shelf.
There is no permanent test hook. Add a temporary env-guarded block at the end of
ShelfController.start() and remove it before finishing:
if ProcessInfo.processInfo.environment["PERCH_UITEST_HOVER"] != nil {
themeStore.showsGrabHandle = true
let seed = FileManager.default.temporaryDirectory
.appendingPathComponent("perch-hover-test.txt")
try? "hover test".write(to: seed, atomically: true, encoding: .utf8)
adoptArrival(ArrivalOffer(url: seed, addedAt: Date()))
revealAtPreferredEdge()
}
A shelf with items stays revealed (retract only fires when empty), so the card is stable for capture. With default (fresh-HOME) settings a one-item card is ~80×62 — nearly the same footprint as the empty tile; don't mistake it for a failed seed. Check the log for "Perch adopted arrival".
python3 has no Quartz module here; use a Swift snippet calling
CGWindowListCopyWindowInfo to get Perch window IDs and bounds (edge tabs
are also Perch windows — pick by size/position).screencapture -o -x -l<windowID>. Never
-R region or full-screen — that once caught the user's personal screen.Popup menus resist scripting. Instead, have the temporary hook register a
DistributedNotificationCenter observer that calls the controller method
(e.g. toggleFreeShelfLock()), then post from the CLI:
swift -e 'import Foundation; DistributedNotificationCenter.default().postNotificationName(Notification.Name("PerchUITestToggleLock"), object: nil, userInfo: nil, deliverImmediately: true)'
Gotcha: a killed instance flushes its store on teardown — rm -rf the test
HOME only after the old process is fully gone, or the store resurrects and the
next run starts with extra items.
Tracking areas follow the real cursor; post CGEvents (.mouseMoved,
.leftMouseDown/Dragged/Up at .cghidEventTap) in small steps with ~40-50ms
sleeps — one teleport can miss enter/exit events. Save the cursor position
first and restore it after. Hover the card's center, not the screen edge, so
the production Perch's edge strips don't trigger.