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
1 change: 1 addition & 0 deletions changelog.d/debugbar-restore-button.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Debug bar: the minimized "Debug" restore button now renders after clicking the X. The `#wdb-minimized` button was nested inside the `#wheels-debugbar` container that `wdbMinimize()` hides with `display:none`, so it could never appear and the bar stayed gone for the whole browser session (manual `sessionStorage` cleanup was the only recovery). It is now a sibling of the container, so minimizing shows the restore button bottom-right and clicking it brings the bar back ([#3345](https://github.com/wheels-dev/wheels/issues/3345)).
6 changes: 4 additions & 2 deletions vendor/wheels/events/onrequestend/debug.cfm
Original file line number Diff line number Diff line change
Expand Up @@ -489,15 +489,17 @@ OR (StructKeyExists(url, "format") AND ListFindNoCase("json,xml,csv,pdf", url.fo
</div>
</cfif>

</div>

<!--- ============ MINIMIZED BUTTON ============ --->
<div id="wdb-minimized" style="display:none;position:fixed;bottom:8px;right:8px;z-index:99999;">
<!--- Sibling of ##wheels-debugbar on purpose: wdbMinimize() sets the container to display:none, and a descendant of a display:none element can never render, so nesting this inside the container makes the restore button unreachable (issue ##3345). It is independently position:fixed. The script include stays below so both elements exist when debugbar.js's load-time wdbMinimize() re-invocation runs. --->
<div id="wdb-minimized" style="all:initial;display:none;position:fixed;bottom:8px;right:8px;z-index:99999;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Oxygen,Ubuntu,sans-serif;">
<button onclick="wdbRestore()" style="background:##1e1e2e;border:1px solid ##45475a;border-radius:8px;padding:6px 10px;cursor:pointer;color:##89b4fa;font-size:12px;font-family:inherit;display:flex;align-items:center;gap:4px;box-shadow:0 2px 8px rgba(0,0,0,.3);">
<svg viewBox="0 0 153 18" xmlns="http://www.w3.org/2000/svg" style="width:20px;height:5px;"><path d="M15.71 12c1.65 0 2.99 1.34 2.99 3s-1.34 3-2.99 3-2.99-1.34-2.99-3v-1.27c0-.42-.15-.79-.45-1.09L6.1 6.45c-.3-.3-.66-.45-1.09-.45H3.75c-1.65 0-2.99-1.34-2.99-3S2.09 0 3.74 0s2.99 1.34 2.99 3v1.27c0 .42.15.79.45 1.09l6.17 6.19c.3.3.66.45 1.09.45z" fill="##f38ba8"/></svg>
Debug
</button>
</div>

<script><cfinclude template="/wheels/public/assets/js/debugbar.js"></script>
</div>
</cfoutput></cfsavecontent><cfoutput>#ReReplace(local.wdbHtml, "(?m)>\s+<", "><", "all")#</cfoutput>
<!--- cfformat-ignore-end --->
81 changes: 81 additions & 0 deletions vendor/wheels/tests/specs/events/DebugBarMinimizedButtonSpec.cfc
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
component extends="wheels.WheelsTest" {

function run() {
describe("debug bar minimized restore button placement", () => {
// wdbMinimize() (public/assets/js/debugbar.js) sets #wheels-debugbar to
// display:none and #wdb-minimized to display:block. A descendant of a
// display:none element is never rendered regardless of its own display
// value, so the "Debug" restore button must be a SIBLING of the
// container, not a child — otherwise clicking the X hides the bar for
// the whole browser session with no visible recovery (issue #3345).
// This spec renders debug.cfm and asserts structurally that
// id="wdb-minimized" appears only after the div balance for
// #wheels-debugbar has returned to zero (sibling, not descendant).
it("renders the wdb-minimized button as a sibling of the debug bar container", () => {
var priorReqWheels = StructKeyExists(request, "wheels") ? Duplicate(request.wheels) : {};

try {
if (!StructKeyExists(request, "wheels")) {
request.wheels = {};
}
request.wheels.execution = {total = 0};
request.wheels.params = {controller = "wheels", action = "tests", route = ""};

// debug.cfm bails out (cfexit) when url.format is one of
// json/xml/csv/pdf so it never breaks an API response. The
// test runner is hit with format=json — clear it for the
// duration of the include so the template renders.
var hadUrlFormat = StructKeyExists(url, "format");
var priorUrlFormat = hadUrlFormat ? url.format : "";
if (hadUrlFormat) {
StructDelete(url, "format");
}

var output = "";
try {
output = application.wo.$includeAndReturnOutput($template = "/wheels/events/onrequestend/debug.cfm");
} finally {
if (hadUrlFormat) {
url.format = priorUrlFormat;
}
}

var containerPos = FindNoCase('id="wheels-debugbar"', output);
expect(containerPos).toBeGT(0, "the ##wheels-debugbar container should render");

var minimizedPos = FindNoCase('id="wdb-minimized"', output);
expect(minimizedPos).toBeGT(0, "the ##wdb-minimized restore button should render");

// Walk <div / </div tokens starting just inside the container's
// opening tag and find where its balance returns to zero (the
// position of the container's own closing tag).
var depth = 1;
var pos = containerPos;
var containerClosePos = 0;
while (depth > 0) {
var nextOpen = FindNoCase("<div", output, pos + 1);
var nextClose = FindNoCase("</div", output, pos + 1);
expect(nextClose).toBeGT(0, "unbalanced markup: ##wheels-debugbar never closes");
if (nextOpen > 0 && nextOpen < nextClose) {
depth += 1;
pos = nextOpen;
} else {
depth -= 1;
pos = nextClose;
containerClosePos = nextClose;
}
}

expect(minimizedPos).toBeGT(
containerClosePos,
"##wdb-minimized must render AFTER ##wheels-debugbar closes (sibling, not descendant) — " &
"nested inside the container, wdbMinimize()'s display:none makes the restore button unreachable (##3345)"
);
} finally {
request.wheels = priorReqWheels;
}
});
});
}

}
Loading