test: align full-suite contracts with unified picker

Issue: #180
User-Visible: no
This commit is contained in:
Sergey Matyunin
2026-08-19 14:24:30 +03:00
parent 6e93aa705c
commit f08c4adabe
2 changed files with 23 additions and 7 deletions
+12 -1
View File
@@ -10,6 +10,15 @@ const res = await page.evaluate(async () => {
while (active?.shadowRoot?.activeElement) active = active.shadowRoot.activeElement;
return active;
};
const composedContains = (root, target) => {
let node = target;
while (node) {
if (node === root) return true;
const tree = node.getRootNode?.();
node = node.parentNode || (tree instanceof ShadowRoot ? tree.host : null);
}
return false;
};
// A11Y-02: the shared native fallback carries the same modal/focus contract
// that ha-dialog supplies in Home Assistant.
@@ -26,7 +35,9 @@ const res = await page.evaluate(async () => {
&& native?.getAttribute('aria-modal') === 'true'
&& !!titleId && !!hp.shadowRoot.getElementById(titleId)?.textContent.trim();
let active = deepActive();
out.initialFocus = !!active && (hp.contains(active) || hp.shadowRoot.contains(active));
// Unified colour controls put the first focus target in their own shadow
// root. Test composed ownership, not only light-DOM containment.
out.initialFocus = !!active && composedContains(hp, active);
const focusable = [...hp.querySelectorAll('button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled])')];
const last = focusable.at(-1);
last?.focus();
+11 -6
View File
@@ -137,6 +137,7 @@ const res = await page.evaluate(async () => {
c._markerDialog = { ...c._markerDialog, name: 'Passive lamp', bindingMode: 'virtual',
binding: 'virtual', lightRole: 'always', lightRoleTouched: true };
await c.updateComplete;
c._setMarkerGlowMode('fixed'); await c.updateComplete;
const glowRadios = [...sr().querySelectorAll('hp-dialog input[name="marker-glow-mode"]')];
out.passiveLiveModeDisabled = glowRadios.find((radio) => radio.value === 'auto')?.disabled === true;
out.passiveManualModesEnabled = glowRadios.filter((radio) => radio.value !== 'auto')
@@ -151,14 +152,18 @@ const res = await page.evaluate(async () => {
&& passiveFields.glow_color?.bri === 0.42;
c._markerDialog = null; await c.updateComplete;
// --- 9) general settings: opacity sliders take the ha branch too -------
// --- 9) #180: general colour opacity now belongs to the shared picker ---
c._openSettingsDialog(); await c.updateComplete;
out.gsHaSliders = sr().querySelectorAll('hp-dialog ha-slider').length >= 9;
const gsl = sr().querySelector('hp-dialog ha-slider');
gsl.value = 55;
gsl.dispatchEvent(new Event('input', { bubbles: true }));
const generalPickers = [...sr().querySelectorAll('hp-dialog hp-color-opacity')];
out.gsUnifiedPickers = generalPickers.length === 12
&& generalPickers.filter((picker) => picker.showOpacity).length === 11;
out.gsNoLegacyHaOpacitySliders = sr().querySelectorAll('hp-dialog ha-slider').length === 0;
generalPickers[0].dispatchEvent(new CustomEvent('hp-color-opacity-change', {
detail: { color: '#123456', opacity: 0.55 }, bubbles: true, composed: true,
}));
await c.updateComplete;
out.gsUpstream = Math.round((Object.values(c._settingsDialog.colors)[0].a) * 100) === 55;
out.gsUpstream = Object.values(c._settingsDialog.colors)
.some((value) => value.c === '#123456' && Math.round(value.a * 100) === 55);
c._settingsDialog = null; await c.updateComplete;
return out;
});