Layers BrowserStack on top of the local Playwright e2e suites:
- browserstack.yml (Windows Chrome, macOS Firefox, iPad/iPhone WebKit,
Galaxy S23) driven by the BrowserStack Node SDK and Local tunnel
- :browserstack package scripts and the gated E2E (BrowserStack) CI job
(runs on manual dispatch or the e2e-browserstack PR label)
- tunnel/iOS-WebKit resilience in the specs (bs-local.com host, single
shared mobile context, dynamic-import + CDP "Internal error" skips)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds Playwright end-to-end tests covering three targets:
- the demo build
- a new lightweight test app exercising several scenarios (theming,
admin/non-admin sidebar, panel navigation, more-info dialog)
- the component gallery
Includes the gulp/rspack build infra for the test app and an "E2E Tests"
GitHub Actions workflow that builds each target once, shares it via
artifacts, and runs the suites on Chromium and mobile Chrome. Browser
install is cached and retried to avoid intermittent download stalls.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* Align integration dashboard grid with design tokens
Replace hardcoded values with design tokens
Add mobile-safe min() in minmax, and add margin/margin-bottom to match
the apps page container spacing.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Remove useless margin bottom
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* Add config panel with cloud to demo
Enable the config panel in the demo and add a logged-in Home Assistant
Cloud account mock so the cloud panel renders with realistic data
(subscription, remote access, text-to-speech, and webhooks).
https://claude.ai/code/session_01LuAsCpbhKpSKufH9FAHNxh
* Add rich mock data for all config panels in demo
Mock the WebSocket commands behind the remaining config panels so they
render with realistic data instead of erroring: integrations, devices,
entities, helpers, automations, scripts, blueprints, voice assistants,
zones, people, logs, backup, about, network, tags, and application
credentials. Adds coherent demo config entries, devices, and integration
manifests so the integrations and devices dashboards are populated.
* Demo: load brand images from CDN and fix more config panels
- Map brand/hardware images to the public brands.home-assistant.io CDN in
demo mode, since there is no backend to serve the token-gated brands API.
- Honor the config entries domain filter so the Bluetooth card is no longer
shown (and Bluetooth, which can't be mocked, stays out of the demo).
- Mock automation/script config and the trigger/condition platform
subscriptions so the automation editor opens.
- Mock search/related so device, entity, and area pages stop erroring.
https://claude.ai/code/session_01LuAsCpbhKpSKufH9FAHNxh
* Demo: mock remaining config WS commands found by crawling
Crawled deep into every config panel (lists, detail pages, editors, and
dialogs) and mocked the WebSocket/REST commands that were still missing:
- auth/sign_path (log download)
- frontend/get_system_data
- config/entity_registry/get_entries (voice assistant expose)
- device_automation trigger/condition/action list + capabilities (device pages)
- validate_config (wired the existing config stub)
- cloud/alexa/entities and cloud/google_assistant/entities (expose)
- config/scene/config REST endpoint (scene editor)
https://claude.ai/code/session_01LuAsCpbhKpSKufH9FAHNxh
* Demo: code-split config panel mocks into a lazy chunk
The config panel mock data is no longer bundled into the demo's main entry
chunk. A loader is registered eagerly at startup and dynamically imports the
config mocks the first time a config-only WS/REST command is requested (i.e.
when the config panel is opened).
- Add mockLazyLoad(shouldLoad, loader) to the mock connection. On an unmocked
command/path matching the predicate it awaits the loader (once) and retries,
so there is no race between panel data fetches and mock registration.
- Move the config-only mocks behind stubs/config-panel.ts, imported lazily.
- Keep manifest/list eager since it is consumed app-wide via the manifests
context and would otherwise pull in the chunk on the regular dashboard.
https://claude.ai/code/session_01LuAsCpbhKpSKufH9FAHNxh
---------
Co-authored-by: Claude <noreply@anthropic.com>
Forward the color option from StateLabelBadgeConfig through to the
underlying entity badge so legacy state-label-badges can pick a color
and pick up state-based icon coloring like hui-entity-badge.
Co-authored-by: Claude <noreply@anthropic.com>
Reverse import/export on grid neutrality gauge
Swap so that export is on the left, and import is on the right. This matches the orientation of the grid energy balance card, and means export is the negative side which visually makes more sense.
* Preserve unchanged entity display entries across registry updates
* Compare all display fields (integration reload can change source-defined ones)
* Use a generic preserveUnchangedRecord helper with deepEqual
* Add deterministic fixtures and characterization tests for chart data processing
* Extract statistics chart data processing into a pure function
* Extract state history line chart data processing into a pure function
* Add benchmark suite for chart data processing
* Add chart data optimization playbook
* Point agent instructions at the chart optimization playbook
The area page resolved device and entity display names by writing them
back onto the registry entries returned by the (memoized) memberships,
which are the shared objects from hass.devices and the entity registry.
That overwrote each entry's raw name during render and leaked app-wide: an
unnamed device would get name set to the localized "Unnamed device", which
then short-circuits the entity-derived fallback elsewhere, and a device or
entity with no user name would have its name field corrupted in the
settings dialog.
Compute the display names on shallow copies and sort/render those instead,
leaving the shared registry objects untouched. The area page renders the
same names and order as before.
* Pass the integration domain to the flow form context
In options flows the flow handler is the config entry id, not the
integration domain. Expose the resolved domain (falling back to the
handler for config flows) on the flow form context so selectors can rely
on the actual domain regardless of the flow type.
* Use the flow domain for serial port recommendations
The serial port selector marked a port as recommended by comparing
matching integrations against `context.handler`. In options flows the
handler is the config entry id, so an integration's own ports were
classified as "not recommended" and labelled "Used by <integration>".
Prefer `context.domain` (with a fallback to `handler`) so the
integration's own ports stay recommended in options flows too.
* Drop the handler fallback for the serial port selector domain
`step-flow-form` is the only context producer that sets `handler`, and it
now always sets `domain` alongside it, so the fallback never resolves to a
different value. In options flows `handler` is the config entry id anyway,
which would be the wrong value to fall back to.