mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-06-19 19:25:27 -04:00
fix(ui): share one z-order stack across Notes and modals (#3798)
* fix(notes): bring pane above active windows * fix(notes): align tool window z-order handoff --------- Co-authored-by: Matyas Fenyves <16389204+uhhgoat@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,139 @@
|
||||
"""Node-driven regression coverage for Notes pane z-order selection.
|
||||
|
||||
Notes uses a body-level backdrop instead of the shared `.modal` element, so the
|
||||
shared tool-window stack helper must account for both Notes and normal modals
|
||||
without importing the full browser-heavy modules.
|
||||
"""
|
||||
|
||||
import json
|
||||
import shutil
|
||||
import subprocess
|
||||
import textwrap
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
HELPER = ROOT / "static" / "js" / "toolWindowZOrder.js"
|
||||
pytestmark = pytest.mark.skipif(not shutil.which("node"), reason="node binary not on PATH")
|
||||
|
||||
|
||||
def _node_eval(source: str):
|
||||
proc = subprocess.run(
|
||||
["node", "--input-type=module"],
|
||||
input=source,
|
||||
cwd=ROOT,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=30,
|
||||
)
|
||||
assert proc.returncode == 0, proc.stderr
|
||||
return json.loads(proc.stdout.strip())
|
||||
|
||||
|
||||
def test_notes_z_order_uses_floor_when_no_tool_windows_are_open():
|
||||
values = _node_eval(
|
||||
textwrap.dedent(
|
||||
f"""
|
||||
import {{ topToolWindowZ }} from '{HELPER.as_uri()}';
|
||||
const root = {{ querySelectorAll() {{ return []; }} }};
|
||||
console.log(JSON.stringify({{ z: topToolWindowZ({{ root, getStyle: () => ({{}}) }}) }}));
|
||||
"""
|
||||
)
|
||||
)
|
||||
|
||||
assert values == {"z": 250}
|
||||
|
||||
|
||||
def test_notes_z_order_lands_above_highest_visible_tool_window():
|
||||
values = _node_eval(
|
||||
textwrap.dedent(
|
||||
f"""
|
||||
import {{ topToolWindowZ }} from '{HELPER.as_uri()}';
|
||||
const cls = (...names) => ({{ contains: (name) => names.includes(name) }});
|
||||
const elements = [
|
||||
{{ id: 'memory', classList: cls(), style: {{ zIndex: '320' }} }},
|
||||
{{ id: 'research', classList: cls(), style: {{ zIndex: '415' }} }},
|
||||
{{ id: 'invalid', classList: cls(), style: {{ zIndex: 'auto' }} }},
|
||||
];
|
||||
const root = {{ querySelectorAll() {{ return elements; }} }};
|
||||
const top = topToolWindowZ({{ root, getStyle: (el) => el.style }});
|
||||
console.log(JSON.stringify({{ top, notes: top + 1 }}));
|
||||
"""
|
||||
)
|
||||
)
|
||||
|
||||
assert values == {"top": 415, "notes": 416}
|
||||
|
||||
|
||||
def test_modal_z_order_handoff_lands_above_notes_tie_on_first_click():
|
||||
values = _node_eval(
|
||||
textwrap.dedent(
|
||||
f"""
|
||||
import {{ nextToolWindowZ }} from '{HELPER.as_uri()}';
|
||||
const cls = (...names) => ({{ contains: (name) => names.includes(name) }});
|
||||
const modal = {{ id: 'modal', classList: cls(), style: {{ zIndex: '416' }} }};
|
||||
const notes = {{ id: 'notes', classList: cls(), style: {{ zIndex: '416' }} }};
|
||||
const elements = [modal, notes];
|
||||
const root = {{ querySelectorAll() {{ return elements; }} }};
|
||||
const z = nextToolWindowZ({{
|
||||
exclude: modal,
|
||||
current: modal.style.zIndex,
|
||||
root,
|
||||
getStyle: (el) => el.style,
|
||||
}});
|
||||
console.log(JSON.stringify({{ z }}));
|
||||
"""
|
||||
)
|
||||
)
|
||||
|
||||
assert values == {"z": 417}
|
||||
|
||||
|
||||
def test_modal_z_order_keeps_current_z_when_already_above_stack():
|
||||
values = _node_eval(
|
||||
textwrap.dedent(
|
||||
f"""
|
||||
import {{ nextToolWindowZ }} from '{HELPER.as_uri()}';
|
||||
const cls = (...names) => ({{ contains: (name) => names.includes(name) }});
|
||||
const modal = {{ id: 'modal', classList: cls(), style: {{ zIndex: '420' }} }};
|
||||
const notes = {{ id: 'notes', classList: cls(), style: {{ zIndex: '416' }} }};
|
||||
const root = {{ querySelectorAll() {{ return [modal, notes]; }} }};
|
||||
const z = nextToolWindowZ({{
|
||||
exclude: modal,
|
||||
current: modal.style.zIndex,
|
||||
root,
|
||||
getStyle: (el) => el.style,
|
||||
}});
|
||||
console.log(JSON.stringify({{ z }}));
|
||||
"""
|
||||
)
|
||||
)
|
||||
|
||||
assert values == {"z": 420}
|
||||
|
||||
|
||||
def test_notes_z_order_ignores_hidden_minimized_and_excluded_windows():
|
||||
values = _node_eval(
|
||||
textwrap.dedent(
|
||||
f"""
|
||||
import {{ topToolWindowZ }} from '{HELPER.as_uri()}';
|
||||
const cls = (...names) => ({{ contains: (name) => names.includes(name) }});
|
||||
const excluded = {{ id: 'notes', classList: cls(), style: {{ zIndex: '900' }} }};
|
||||
const elements = [
|
||||
excluded,
|
||||
{{ id: 'hidden-class', classList: cls('hidden'), style: {{ zIndex: '800' }} }},
|
||||
{{ id: 'minimized', classList: cls('modal-minimized'), style: {{ zIndex: '700' }} }},
|
||||
{{ id: 'display-none', classList: cls(), style: {{ zIndex: '600', display: 'none' }} }},
|
||||
{{ id: 'visibility-hidden', classList: cls(), style: {{ zIndex: '500', visibility: 'hidden' }} }},
|
||||
{{ id: 'visible', classList: cls(), style: {{ zIndex: '310' }} }},
|
||||
];
|
||||
const root = {{ querySelectorAll() {{ return elements; }} }};
|
||||
const top = topToolWindowZ({{ exclude: excluded, root, getStyle: (el) => el.style }});
|
||||
console.log(JSON.stringify({{ top }}));
|
||||
"""
|
||||
)
|
||||
)
|
||||
|
||||
assert values == {"top": 310}
|
||||
Reference in New Issue
Block a user