You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
data-bs-toggle="dropdown" toggles inside the portal chrome (the per-portlet Options menu, possibly others) do not open via JavaScript-dispatched clicks. Specifically:
Playwright's Locator.click() on a .portlet-options-menu .dropdown-toggle element completes successfully but leaves aria-expanded at "false" — the menu does not render.
Native HTMLElement.click() from a page.evaluate() block has the same outcome.
Dispatching synthetic MouseEvent("click", { bubbles: true }), PointerEvent("pointerdown"), MouseEvent("mousedown"), etc., from JS produces the same outcome.
Bootstrap's auto-init did register an instance — bootstrap.Dropdown.getInstance(toggleEl) returns a non-null Dropdown object — so the wiring exists.
Calling bootstrap.Dropdown.getOrCreateInstance(toggleEl).show() directly opens the menu reliably and aria-expanded flips to "true". So the Bootstrap component itself is healthy; only the click→delegate path is broken.
This pattern points to a listener somewhere in uPortal's own chrome JS that is swallowing the click event before it bubbles to document, where Bootstrap 5's delegated [data-bs-toggle="dropdown"] handler lives. Candidates: jQuery UI draggable's mousedown/click plumbing on .up-portlet-wrapper, jQuery click delegations registered against .up-portlet-options-item ancestors, or something in modern-layout-preferences.js. The exact culprit is not yet identified.
Why this matters beyond the test suite
The same JS-delivered click path that Playwright uses is what assistive tech (screen readers' click activation), keyboard-driven flows that synthesize clicks, and any custom uPortal JS that programmatically opens the menu would use. Real human pointer/touch clicks may still work — that's the symptom variance — but anything that delivers a click programmatically will silently fail to open the menu.
Reproduction
Deploy uPortal 5.17.5 (with the Bootstrap dedupe fix merged) to a Tomcat with the respondr skin and a quickstart layout.
Log in as a regular user. Navigate to any tab with a movable portlet (e.g. Calendar on the Welcome tab).
Open DevTools and run:
consttoggle=document.querySelector(".up-portlet-wrapper:has(.portlet-title a[title='Calendar']) .portlet-options-menu .dropdown-toggle");// Confirm Bootstrap auto-init wired the instance:bootstrap.Dropdown.getInstance(toggle);// → returns a Dropdown object (auto-init ran)// But neither of these opens the menu — aria-expanded stays "false":toggle.click();toggle.dispatchEvent(newMouseEvent("click",{bubbles: true}));// This *does* open the menu:bootstrap.Dropdown.getOrCreateInstance(toggle).show();
The same behavior was observed against the Bookmarks portlet's Options menu and against any maximized portlet's Options menu, so it isn't Calendar-specific — it's the chrome.
Workaround in uPortal-start tests
uPortal-start/tests/ux/utils/ux-general-utils.ts now exposes an openDropdown(toggle) helper that goes through Bootstrap's public API:
exportasyncfunctionopenDropdown(toggle: Locator): Promise<void>{awaitexpect(toggle).toBeVisible();awaittoggle.evaluate((el)=>{constbs=(windowasany).bootstrap;if(!bs?.Dropdown)thrownewError("Bootstrap Dropdown not loaded");bs.Dropdown.getOrCreateInstance(elasHTMLElement).show();});awaitexpect(toggle).toHaveAttribute("aria-expanded","true");}
smoke/favorites.spec.ts and smoke/portlet-options.spec.ts use it everywhere they previously did toggle.click(). The suite is now stable at 117/117 across multiple full-suite runs.
The tradeoff: those tests no longer exercise the click-pathway specifically, so a regression in the click→Bootstrap chain won't surface in CI. That's the gap this issue tracks.
Suggested investigation steps
In a running portal page, attach a capture-phase click listener at document level: document.addEventListener('click', e => console.log('click target:', e.target, 'phase:', e.eventPhase, 'cancelBubble:', e.cancelBubble), true);. Then call toggle.click() from DevTools. If the listener doesn't fire, the click is being canceled at the element or via stopImmediatePropagation upstream of document.
If the document-level listener does fire but the Bootstrap delegate doesn't, check whether jQuery's $('document').off('click.bs.dropdown.data-api') was called somewhere during page init (Bootstrap 5's data-api uses native listeners, but if a jQuery plugin did this against jQuery's own delegate set, that's a smell worth chasing).
Search media/skins/common/javascript/ and modern-layout-preferences.js for stopImmediatePropagation / preventDefault against click/mousedown.
Related
#2980 (Bootstrap dedupe fix) — fixed a different symptom in the same chain (Bootstrap loaded twice → click opened then immediately closed). After that fix, dropdown is loaded once, the auto-init runs, but synthetic clicks still don't fire the open. Different problem, same surface.
Problem
data-bs-toggle="dropdown"toggles inside the portal chrome (the per-portlet Options menu, possibly others) do not open via JavaScript-dispatched clicks. Specifically:Locator.click()on a.portlet-options-menu .dropdown-toggleelement completes successfully but leavesaria-expandedat"false"— the menu does not render.HTMLElement.click()from apage.evaluate()block has the same outcome.MouseEvent("click", { bubbles: true }),PointerEvent("pointerdown"),MouseEvent("mousedown"), etc., from JS produces the same outcome.bootstrap.Dropdown.getInstance(toggleEl)returns a non-nullDropdownobject — so the wiring exists.bootstrap.Dropdown.getOrCreateInstance(toggleEl).show()directly opens the menu reliably andaria-expandedflips to"true". So the Bootstrap component itself is healthy; only the click→delegate path is broken.This pattern points to a listener somewhere in uPortal's own chrome JS that is swallowing the click event before it bubbles to
document, where Bootstrap 5's delegated[data-bs-toggle="dropdown"]handler lives. Candidates: jQuery UI draggable'smousedown/clickplumbing on.up-portlet-wrapper, jQuery click delegations registered against.up-portlet-options-itemancestors, or something inmodern-layout-preferences.js. The exact culprit is not yet identified.Why this matters beyond the test suite
The same JS-delivered click path that Playwright uses is what assistive tech (screen readers' click activation), keyboard-driven flows that synthesize clicks, and any custom uPortal JS that programmatically opens the menu would use. Real human pointer/touch clicks may still work — that's the symptom variance — but anything that delivers a click programmatically will silently fail to open the menu.
Reproduction
Deploy uPortal 5.17.5 (with the Bootstrap dedupe fix merged) to a Tomcat with the
respondrskin and a quickstart layout.Log in as a regular user. Navigate to any tab with a movable portlet (e.g. Calendar on the Welcome tab).
Open DevTools and run:
The same behavior was observed against the Bookmarks portlet's Options menu and against any maximized portlet's Options menu, so it isn't Calendar-specific — it's the chrome.
Workaround in uPortal-start tests
uPortal-start/tests/ux/utils/ux-general-utils.tsnow exposes anopenDropdown(toggle)helper that goes through Bootstrap's public API:smoke/favorites.spec.tsandsmoke/portlet-options.spec.tsuse it everywhere they previously didtoggle.click(). The suite is now stable at 117/117 across multiple full-suite runs.The tradeoff: those tests no longer exercise the click-pathway specifically, so a regression in the click→Bootstrap chain won't surface in CI. That's the gap this issue tracks.
Suggested investigation steps
documentlevel:document.addEventListener('click', e => console.log('click target:', e.target, 'phase:', e.eventPhase, 'cancelBubble:', e.cancelBubble), true);. Then calltoggle.click()from DevTools. If the listener doesn't fire, the click is being canceled at the element or via stopImmediatePropagation upstream ofdocument.$('document').off('click.bs.dropdown.data-api')was called somewhere during page init (Bootstrap 5's data-api uses native listeners, but if a jQuery plugin did this against jQuery's own delegate set, that's a smell worth chasing).media/skins/common/javascript/andmodern-layout-preferences.jsforstopImmediatePropagation/preventDefaultagainst click/mousedown.Related
uPortal-startPR UP-4702: Add support for encrypted values to the property files with… #692 captures the diagnostic walkthrough.