import assert from "node:assert/strict"; import { readFileSync } from "node:fs"; const read = name => readFileSync(new URL(name, import.meta.url), "utf8"); const shell = read("./shell.qml"); const privilege = read("./PrivilegeSurface.qml"); const overlay = read("./NokoFocusOverlay.qml"); const text = read("./NuguText.qml"); assert.doesNotMatch(shell, /component (?:PrivilegeSurface|PrivilegeFailureShake|NokoFocusOverlay|NuguText):/, "shell delegates extracted trees"); assert.doesNotMatch(shell, /\bNuguText\s*\{/, "no shell-local text callers remain"); assert.match(shell, /PrivilegeSurface\s*\{\s*id: privilegeSurface\s*anchors.fill: parent\s*theme: nuguTheme\s*privilegeService: privilege/, "shell owns privilege geometry and injects dependencies"); assert.match(shell, /NokoFocusOverlay\s*\{\s*anchors.fill: parent\s*theme: nuguTheme\s*nokoService: noko\s*niriService: niri\s*barHeight: nokoOverlayWindow.modelData.name === shell.primaryScreenName \? surfaceManager.barHeight : 0\s*orientation: shell.orientation/, "shell owns overlay geometry and injects dependencies"); for (const source of [privilege, overlay]) { assert.match(source, /required property Theme theme/); assert.doesNotMatch(source, /\b(?:shell|nuguTheme|surfaceManager)\b/, "no composition-root id capture"); assert.doesNotMatch(source, /childrenRect/, "no child-bounds sizing"); assert.doesNotMatch(source, /\bselected\s*:/, "all extracted text uses shared unselected semantics"); } assert.match(text, /property bool selected: false/); assert.match(text, /color: !theme \? "transparent" : \(variant === "title" \? theme.ui.important_global : \(variant === "meta" \? theme.ui.normal : theme.content.normal\)\)/); assert.match(text, /font.family: variant === "mono" \? "IBM Plex Mono" : "IBM Plex Sans"/); assert.match(text, /font.pixelSize: variant === "title" \? 15 : \(variant === "meta" \? 13 : 14\)/); assert.match(text, /font.bold: variant === "title"/); assert.match(text, /elide: Text.ElideRight/); assert.match(privilege, /required property Privilege privilegeService/); assert.match(privilege, /import "privilege.js" as PrivilegeUi/); const shake = privilege.slice(privilege.indexOf("component PrivilegeFailureShake:")); assert.match(shake, /required property Theme theme/); assert.doesNotMatch(shake, /implicitWidth:|implicitHeight:/, "shake geometry comes only from its caller"); assert.equal((shake.match(/duration: shakeRoot.theme.lowPowerMode \? 0 : /g) || []).length, 5, "all five shake steps use the injected theme"); assert.match(privilege, /PrivilegeFailureShake\s*\{\s*theme: root.theme[\s\S]*?width: parent.width\s*height: inputColumn.implicitHeight/, "shake caller owns both axes"); for (const action of ["submit(secret)", "deny()", "cancel()"]) assert.ok(privilege.includes(`refreshFrom(privilegeService.${action})`), `preserved privilege route: ${action}`); assert.match(overlay, /required property Noko nokoService/); assert.match(overlay, /required property Niri niriService/); assert.match(overlay, /readonly property string phase: nokoService \? nokoService.overlayState : ""/); assert.match(overlay, /readonly property real usableX: verticalBar \? barHeight : 0/); assert.match(overlay, /readonly property real usableY: verticalBar \? 0 : barHeight/); assert.match(overlay, /running: overlay.visible && overlay.phase !== "finished"\s*onTriggered: overlay.tick\+\+/); assert.match(overlay, /duration: overlay.theme && overlay.theme.lowPowerMode \? 0 : 90/); console.log("shell-composition.test.mjs: ALL PASS");