diff --git a/frontend-modern/browser-verification.json b/frontend-modern/browser-verification.json index 20516b392..88e568401 100644 --- a/frontend-modern/browser-verification.json +++ b/frontend-modern/browser-verification.json @@ -1,23 +1,16 @@ { "version": 1, - "base_sha": "4f11deddc728a69f937dcb04777c9e44276c3f95", - "verified_at": "2026-09-23T11:26:00Z", + "base_sha": "3b1b43293e21d06d1286124f96f78b1247443dea", + "verified_at": "2026-09-24T09:02:03Z", "result": "passed", "changed_paths": [ - "frontend-modern/src/features/proxmox/ProxmoxBackupServersTable.tsx", - "frontend-modern/src/types/resource.ts" + "frontend-modern/src/components/Settings/BrandingSettingsCard.tsx" ], "content_sha256": { - "frontend-modern/src/features/proxmox/ProxmoxBackupServersTable.tsx": "f6b50e71870ca4a3e0dcfa3e47413542e8444296bc68481c60e15d1a5d921f9f", - "frontend-modern/src/types/resource.ts": "db2509b73b2ed550ea1890aaef34e2a3dfe7d500aa193586562f9e20b95283ab" + "frontend-modern/src/components/Settings/BrandingSettingsCard.tsx": "6516a05aff71b1d96660f81189b6df8bceccf7e94d15d6c3213556e794f2ae40" }, "routes": [ - "/browser-tests/pbs-host-history-correlation.html?topology=guest&order=stable (Proxmox Backups server drawer)", - "/browser-tests/pbs-host-history-correlation.html?topology=guest&order=reordered (Proxmox Backups server drawer)", - "/browser-tests/pbs-host-history-correlation.html?topology=pbs-only&order=stable (Proxmox Backups server drawer)", - "/browser-tests/pbs-host-history-correlation.html?topology=pbs-only&order=reordered (Proxmox Backups server drawer)", - "/browser-tests/pbs-host-history-correlation.html?topology=side-by-side&order=stable (Proxmox Backups server drawer)", - "/browser-tests/pbs-host-history-correlation.html?topology=side-by-side&order=reordered (Proxmox Backups server drawer)" + "/settings/system-general (Application branding card, Header preview)" ], "viewports": [ { @@ -30,18 +23,15 @@ } ], "states": [ - "PBS connection configured by 10.0.0.5 and linked to the host agent only by the reported pbs.nodeName, across pbs-only, side-by-side and PVE-guest topologies", - "Drawer History tab selected with a populated correlated host series", - "Timer-driven snapshot replacing the datastore inventory in stable and reversed order", - "Snapshot that briefly omits the correlated host row while the PBS server row remains", - "Snapshot that restores the correlated host row on the same selection" + "No custom logo and no custom name: the preview falls back to the default Pulse lockup", + "Light colour scheme at 1280x900 and 390x844", + "Dark colour scheme at 1280x900" ], "interactions": [ - "Expand the Proxmox Backups server row, switch between datastore rows and select History; assert the chart paths render against the host metrics target even though the configured endpoint is not a machine-identity token", - "Apply timer-driven stable and reordered snapshots; assert the drawer is not remounted, the History selection is retained, the chart series survive and the Discovery/Metrics Target rows stay byte-identical", - "Apply a snapshot that omits the correlated host row; assert the Identity rows and History chart stay on the retained host target instead of falling back to the PBS service key", - "Restore the correlated host row; assert the same target is confirmed, and repeat the complete matrix at 1280x900 and 390x844" + "Open Settings > General with the white_label capability present; assert the Header preview renders exactly one svg.pulse-brand-logo (blue disc, white ring, white centre dot) and no \"\u25cf\" text glyph", + "Compare the preview mark with the page header lockup: both render PulseBrandMark at 20px", + "Check the page does not scroll horizontally at 390px wide" ], - "command": "pulse-worker-browser scripts/check-pbs-host-history-correlation.cjs", - "notes": "Chromium 141.0.7390.37 / Playwright 1.56.1. Production ProxmoxBackupServersTable mounted through the real browser fixture with synthetic API responses and an intercepted metrics-history request. Proves the reported-node-name host correlation and its retention across a transient host-row omission, not backend persistence or installed release behaviour. The recorded history requests target agent/agent-proxback and vm/proxmox:100 and never the PBS service target agent/pbs-1. The same check fails on the pre-fix source: the drawer falls back to the PBS service key when the endpoint is not a machine-identity token, and omitting the host row flips the Discovery and Metrics Target rows to agent:pbs-1." + "command": "node verify.mjs (Playwright against a private mock-mode backend on :7681 and Vite on :5199)", + "notes": "Chromium via Playwright 1.56.1 from repos/pulse/node_modules. Real app and backend in PULSE_MOCK_MODE with ALLOW_ADMIN_BYPASS; the only stub is /api/license/runtime-capabilities with white_label added, because the mock install has no white-label entitlement and the card is gated behind it. Before the fix the same preview drew a blue circle containing a \"\u25cf\" text character instead of the Pulse brand mark, as seen in a provider-hosted client workspace on the walkthrough lab. Console errors were only the mock environment's failing update check." } diff --git a/frontend-modern/src/components/Settings/BrandingSettingsCard.tsx b/frontend-modern/src/components/Settings/BrandingSettingsCard.tsx index 27415994f..b7830c18d 100644 --- a/frontend-modern/src/components/Settings/BrandingSettingsCard.tsx +++ b/frontend-modern/src/components/Settings/BrandingSettingsCard.tsx @@ -1,6 +1,7 @@ import { Show, createSignal, type Accessor, type Component, type Setter } from 'solid-js'; import ImageIcon from 'lucide-solid/icons/image'; import Trash2 from 'lucide-solid/icons/trash-2'; +import { PulseBrandMark } from '@/components/Brand/PulseBrandMark'; import { Button } from '@/components/shared/Button'; import { FeatureGateSection } from '@/components/shared/FeatureGateSection'; import { formControl, formHelpText, formLabel } from '@/components/shared/Form'; @@ -157,11 +158,7 @@ export const BrandingSettingsCard: Component = (props
- ● - - } + fallback={} > {(logo) => ( { expect(brandingLogoPreview('YWJj', 'png')).toBe('data:image/png;base64,YWJj'); }); + // Without a custom logo the preview must show what the header shows: the + // real Pulse brand mark, not a stand-in glyph. + it('previews the default header with the Pulse brand mark', () => { + const { container } = render(() => ( + ''} + setDisplayName={() => ''} + logoBase64={() => ''} + setLogoBase64={() => ''} + logoFormat={() => ''} + setLogoFormat={() => ''} + setHasUnsavedChanges={() => false} + /> + )); + const mark = container.querySelector('svg.pulse-brand-logo'); + expect(mark).not.toBeNull(); + expect(mark?.querySelectorAll('circle')).toHaveLength(3); + expect(container.textContent).not.toContain('●'); + expect(screen.queryByTestId('branding-logo-preview')).toBeNull(); + }); + it('updates the application name and marks settings dirty', async () => { const state = renderCard();