refactor: extract shouldShowClearExitNode and isActiveExitNode to lib.js (TDD) — light progress on #43
- Two small pure UI predicates moved out of QML delegate - QML now calls TailscaleLib.* (thinner glue) - New tests + all existing tests pass - No new state, no architecture change Written by AI agent working for @jtmorris. Model: Grok build-0.1.
This commit is contained in:
parent
925233dfb9
commit
440e954099
3 changed files with 24 additions and 4 deletions
|
|
@ -202,7 +202,7 @@ PluginComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
visible: root.currentExitNode !== ""
|
visible: TailscaleLib.shouldShowClearExitNode(root.currentExitNode)
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
@ -292,7 +292,7 @@ PluginComponent {
|
||||||
id: exitNodeButton
|
id: exitNodeButton
|
||||||
text: "↗"
|
text: "↗"
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: root.currentExitNode === modelData.hostname ? Theme.primary : Theme.surfaceVariantText
|
color: TailscaleLib.isActiveExitNode(root.currentExitNode, modelData.hostname) ? Theme.primary : Theme.surfaceVariantText
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,15 @@ function getStrings() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Light UI predicates extracted from QML (advances #43 — keeps view thin)
|
||||||
|
function shouldShowClearExitNode(currentExitNode) {
|
||||||
|
return currentExitNode !== ""
|
||||||
|
}
|
||||||
|
|
||||||
|
function isActiveExitNode(currentExitNode, hostname) {
|
||||||
|
return currentExitNode === hostname
|
||||||
|
}
|
||||||
|
|
||||||
function parseStatusResult(jsonText) {
|
function parseStatusResult(jsonText) {
|
||||||
try {
|
try {
|
||||||
const data = JSON.parse(jsonText)
|
const data = JSON.parse(jsonText)
|
||||||
|
|
@ -108,5 +117,5 @@ function errorMessage(cmd) {
|
||||||
|
|
||||||
// CommonJS export for Node.js tests (ignored by QML)
|
// CommonJS export for Node.js tests (ignored by QML)
|
||||||
if (typeof module !== "undefined" && module.exports) {
|
if (typeof module !== "undefined" && module.exports) {
|
||||||
module.exports = { parsePeers, makeExitNodeCommand, findActiveExitNode, errorMessage, validateClipboardTool, buildCopyCommand, nextClipboardTool, allClipboardTools, buildToggleCommand, parseStatusResult, getStrings }
|
module.exports = { parsePeers, makeExitNodeCommand, findActiveExitNode, errorMessage, validateClipboardTool, buildCopyCommand, nextClipboardTool, allClipboardTools, buildToggleCommand, parseStatusResult, getStrings, shouldShowClearExitNode, isActiveExitNode }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { test } from "node:test"
|
import { test } from "node:test"
|
||||||
import assert from "node:assert"
|
import assert from "node:assert"
|
||||||
import lib from "../tailscalectl/lib.js"
|
import lib from "../tailscalectl/lib.js"
|
||||||
const { parsePeers, makeExitNodeCommand, findActiveExitNode, errorMessage, validateClipboardTool, buildCopyCommand, nextClipboardTool, allClipboardTools, buildToggleCommand, parseStatusResult, getStrings } = lib
|
const { parsePeers, makeExitNodeCommand, findActiveExitNode, errorMessage, validateClipboardTool, buildCopyCommand, nextClipboardTool, allClipboardTools, buildToggleCommand, parseStatusResult, getStrings, shouldShowClearExitNode, isActiveExitNode } = lib
|
||||||
|
|
||||||
test("parsePeers extracts exitNode from ExitNodeOption", () => {
|
test("parsePeers extracts exitNode from ExitNodeOption", () => {
|
||||||
const peerMap = {
|
const peerMap = {
|
||||||
|
|
@ -157,6 +157,17 @@ test("getStrings.copied interpolates the text", () => {
|
||||||
assert.ok(msg.includes("100.64.0.5"))
|
assert.ok(msg.includes("100.64.0.5"))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test("shouldShowClearExitNode returns true only when there is a current exit node", () => {
|
||||||
|
assert.strictEqual(shouldShowClearExitNode("router"), true)
|
||||||
|
assert.strictEqual(shouldShowClearExitNode(""), false)
|
||||||
|
})
|
||||||
|
|
||||||
|
test("isActiveExitNode correctly identifies the active exit node button", () => {
|
||||||
|
assert.strictEqual(isActiveExitNode("gluetun-sjc", "gluetun-sjc"), true)
|
||||||
|
assert.strictEqual(isActiveExitNode("gluetun-sjc", "gluetun-den"), false)
|
||||||
|
assert.strictEqual(isActiveExitNode("", "router"), false)
|
||||||
|
})
|
||||||
|
|
||||||
// --- buildToggleCommand ---
|
// --- buildToggleCommand ---
|
||||||
|
|
||||||
test("buildToggleCommand returns down command when connected", () => {
|
test("buildToggleCommand returns down command when connected", () => {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue