- hypr/apps.lua - hypr/autostart.lua - hypr/envs.lua - hypr/hyprland.lua - hypr/hyprsunset.conf - hypr/input.lua - hypr/looknfeel.lua - hypr/omasettings.lua - hypr/xdph.conf - omarchy/branding/about.txt - omarchy/branding/screensaver.txt - omarchy/extensions/omarchy-menu.jsonc - omarchy/hooks/battery-low.d/play-warning-sound.sample - omarchy/hooks/font-set.d/show-font-notification.sample - omarchy/hooks/post-boot.d/weather.sample - omarchy/hooks/post-update.d/install-voxtype.hook - omarchy/hooks/post-update.d/setup-agent.hook - omarchy/hooks/post-update.d/setup-fingerprint.hook - omarchy/hooks/post-update.d/show-update-notification.sample - omarchy/hooks/pre-refresh-pacman.d/add-custom-repo.sample - omarchy/hooks/theme-set.d/show-theme-notification.sample - omarchy/shell.json - omarchy/shell.toml - omarchy/theme.name - omarchy/themes/azure-glow/README.md - omarchy/themes/azure-glow/alacritty.toml - omarchy/themes/azure-glow/btop.theme - omarchy/themes/azure-glow/hyprland.conf - omarchy/themes/azure-glow/hyprlock.conf - omarchy/themes/azure-glow/icons.theme - … 269 more
76 lines
3.6 KiB
JavaScript
76 lines
3.6 KiB
JavaScript
#!/usr/bin/env node
|
|
// Transient status and error messages float over the panel instead of joining
|
|
// its content column. Their arrival must never change the height used by
|
|
// KeyboardPanel, which is what made every screen jump down and back up.
|
|
//
|
|
// node tests/status-notice.test.js
|
|
|
|
const fs = require("fs")
|
|
const path = require("path")
|
|
|
|
const panelSrc = fs.readFileSync(path.join(__dirname, "..", "Panel.qml"), "utf8")
|
|
const noticeSrc = fs.existsSync(path.join(__dirname, "..", "StatusNotice.qml"))
|
|
? fs.readFileSync(path.join(__dirname, "..", "StatusNotice.qml"), "utf8")
|
|
: ""
|
|
let pass = 0
|
|
const failures = []
|
|
const check = (label, ok, detail) => ok ? pass++ : failures.push(`${label}\n ${detail}`)
|
|
|
|
const noticeAt = panelSrc.indexOf("id: statusNotice")
|
|
const noticeUse = noticeAt === -1 ? "" : panelSrc.slice(noticeAt, noticeAt + 2000)
|
|
|
|
check("the status notice is a sibling overlay rather than a mainColumn child",
|
|
/^ StatusNotice \{\n id: statusNotice/m.test(panelSrc),
|
|
"expected statusNotice at PanelKeyCatcher child indentation")
|
|
check("the overlay is pinned inside the bottom of the panel",
|
|
/anchors\.bottom:\s*parent\.bottom/.test(noticeSrc)
|
|
&& /anchors\.horizontalCenter:\s*parent\.horizontalCenter/.test(noticeSrc)
|
|
&& /z:\s*[1-9][0-9]*/.test(noticeSrc),
|
|
noticeSrc)
|
|
check("the overlay never participates in panel height measurement",
|
|
/contentHeight:\s*panel\.fittedContentHeight\(mainColumn\.implicitHeight/.test(panelSrc)
|
|
&& !/implicitHeight:\s*statusNotice/.test(panelSrc),
|
|
"KeyboardPanel must continue to measure only mainColumn")
|
|
|
|
check("errors take priority over transient status text",
|
|
/showsError:\s*root\.errorMessage\s*!==\s*""/.test(noticeSrc)
|
|
&& /text:\s*root\.showsError\s*\?\s*root\.errorMessage\s*:\s*root\.statusMessage/.test(noticeSrc),
|
|
noticeSrc)
|
|
check("status text still yields to the sequential TOTP action",
|
|
/showsStatus:[^\n]*root\.statusMessage\s*!==\s*""[^\n]*!root\.statusSuppressed/.test(noticeSrc)
|
|
&& /statusSuppressed:\s*root\.totpFollowupActive/.test(noticeUse),
|
|
noticeSrc + "\n" + noticeUse)
|
|
check("long messages wrap within the panel",
|
|
/wrapMode:\s*Text\.Wrap/.test(noticeSrc), noticeSrc)
|
|
check("errors can be dismissed without hiding ordinary status updates",
|
|
/visible:\s*root\.showsError/.test(noticeSrc)
|
|
&& /onClicked:\s*root\.errorDismissed\(\)/.test(noticeSrc)
|
|
&& /onErrorDismissed:[\s\S]{0,400}root\.errorMessage = ""/.test(noticeUse),
|
|
noticeSrc + "\n" + noticeUse)
|
|
|
|
// An error the user can act on carries the action. A refused save is the case:
|
|
// the list is already back to what the vault holds, so the button is the way
|
|
// back to what was typed.
|
|
check("an error can offer a recovery alongside the dismiss",
|
|
/property string actionLabel: ""/.test(noticeSrc)
|
|
&& /signal actionRequested\(\)/.test(noticeSrc)
|
|
&& /visible: root\.showsError && root\.actionLabel !== ""/.test(noticeSrc),
|
|
noticeSrc)
|
|
check("the recovery is offered only when there is one",
|
|
/actionLabel: root\.failedSave \? "Reopen " \+ root\.failedSave\.name : ""/.test(noticeUse),
|
|
noticeUse)
|
|
check("dismissing the message discards the recovery with it",
|
|
/root\.failedSave = null\s*\n\s*root\.errorMessage = ""/.test(noticeUse),
|
|
"a Reopen button behind an invisible message is a button for nothing")
|
|
check("dynamic notices expose alert semantics to assistive technology",
|
|
/Accessible\.role:\s*Accessible\.AlertMessage/.test(noticeSrc)
|
|
&& /Accessible\.ignored:\s*!root\.shown/.test(noticeSrc)
|
|
&& /Accessible\.name:/.test(noticeSrc),
|
|
noticeSrc)
|
|
|
|
console.log(`${pass} passed, ${failures.length} failed`)
|
|
if (failures.length) {
|
|
console.error("\nFAILURES:\n " + failures.join("\n "))
|
|
process.exit(1)
|
|
}
|