Admit serviceprocess server-side and give Operator Reports its own tab

asset_panels() rewrites any group missing from ASSET_PANEL_GROUPS to 'details' before the client sees it, and Phase 3 never added 'serviceprocess' there. Both panels were relabelled on the wire, so the tab could not appear no matter how consistent the frontend was. That is why the tab was still missing after the schema fix - a second, unrelated cause wearing the same symptom.

Operator Reports moves out of System Monitors into a tab of its own: that tab is machine-collected health, this is a person reporting something, and the thumbnail grid dwarfed the fact cards it sat between. Full width, since it is alone in the tab.

panelGroups.spec.js claimed to cover four files and checked two; it now reads the server tuple as well. The plugin test's hand-copied set was a fifth copy and now derives from the server tuple instead.
This commit is contained in:
benjamin.baker
2026-09-05 07:37:01 -04:00
parent f77a288bdc
commit 7f84e8ca1e
7 changed files with 103 additions and 9 deletions

View File

@@ -0,0 +1,44 @@
"""The server-side panel group vocabulary must admit every group a plugin uses.
`asset_panels()` resolves a panel's group BEFORE the client sees it, coercing
any unrecognised value to 'details'. That makes ASSET_PANEL_GROUPS a third copy
of the tab vocabulary, alongside RENDERED_GROUPS in PluginAssetPanels.vue and
the tab list in PCDetail.vue. Phase 3 added 'serviceprocess' to the two
frontend copies and missed this one, so both Service/Process panels were
silently relabelled 'details' on the wire and the tab never appeared.
The failure is invisible: no error, no log line, and the panels still render -
just in the wrong tab, underneath the Details cards.
"""
from shopdb.core.api.pluginui import ASSET_PANEL_GROUPS
from plugins.endpoints.plugin import EndpointsPlugin
def test_every_group_the_endpoints_plugin_declares_survives_resolution():
declared = {
str(panel.get('group') or '').strip().lower()
for panel in EndpointsPlugin().get_asset_panels()
}
declared.discard('')
unknown = declared - set(ASSET_PANEL_GROUPS)
assert not unknown, (
f'panels declare {sorted(unknown)}, which the server rewrites to '
"'details' - the tab will not appear"
)
def test_serviceprocess_is_admitted():
# Named explicitly: the generic test above would also pass if the
# serviceprocess panels were deleted outright.
assert 'serviceprocess' in ASSET_PANEL_GROUPS
def test_reports_is_admitted():
# Same reasoning as serviceprocess above. Operator Reports was moved out of
# System Monitors into a tab of its own, which is the same three-copy
# change that Phase 3 got wrong.
assert 'reports' in ASSET_PANEL_GROUPS
def test_details_remains_the_fallback():
assert ASSET_PANEL_GROUPS[0] == 'details'