""" The sidebar's Node section follows the account's node link, and must follow it when it changes -- not only at sign-in. Reported on a real install: after the first click on Create group, the Node section (Node, Create group) was gone from the sidebar until a reload, while the group was created and the node ran. `hasNodeKey` was read once per session change and never again, so a node linked by the wizard stayed out of the sidebar; and the one read there was swallowed its errors, so a session blip (a refused renewal, then the desktop app's silent device sign-in) followed by one failed request left the section hidden for good. Read from the source, like the rest of the SPA's wiring tests: the state lives inside App, and what matters is the seam between two modules. """ import re from pathlib import Path STATIC = Path(__file__).resolve().parents[1] / "src" / "meshbay_hub" / "static" APP = (STATIC / "app.js").read_text(encoding="utf-8") WIZARD = (STATIC / "create-group-page.js").read_text(encoding="utf-8") def _body(src: str, start: str, end: str) -> str: return src.split(start, 1)[1].split(end, 1)[0] def test_the_create_group_page_can_tell_the_app_a_node_was_linked(): page = _body(APP, "<${LazyCreateGroupPage}", "/>`;") assert "onNodeLinked=${refreshNodeKey}" in page created = _body(page, "onCreated=${() => {", "}}") assert "refreshNodeKey()" in created def test_the_wizard_says_so_after_each_way_it_links_one(): link = _body(WIZARD, "const linkNodeKey = useCallback(", "}, [") assert link.index("/v1/users/me/node_key") < link.index("onNodeLinked()"), ( "the app must be told after the hub has the key, not before") start = _body(WIZARD, "const startNode = useCallback(", "}, [") assert start.index("platform.node.start(") < start.index("onNodeLinked()") def test_one_failed_read_does_not_hide_the_section_for_good(): refresh = _body(APP, "const refreshNodeKey = useCallback(", "}, [user]);") assert "/pubkeys" in refresh assert not re.search(r"\.catch\(\(\)\s*=>\s*\{\s*\}\)", refresh), ( "a swallowed failure leaves hasNodeKey false until a reload") assert "setTimeout(" in refresh, "a failed read is tried again" assert "nodeKeyAskedForRef.current === user" in refresh, ( "a late answer must not land on a session that has changed") def test_the_session_effect_uses_the_same_read(): assert APP.count("/pubkeys`") == 1, "one place decides hasNodeKey"