Skip to content

Commit 31eafd6

Browse files
committed
Fix a bug with default_panel option and update Home Assistant to version 2026.8.0b4
1 parent 8d9d947 commit 31eafd6

5 files changed

Lines changed: 105 additions & 14 deletions

File tree

.hass/config/.HA_VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2026.8.0b3
1+
2026.8.0b4

dist/custom-sidebar-plugin.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/docs/08-troubleshooting/index.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import DocCardList from '@theme/DocCardList';
66

77
# Troubleshooting
88

9-
This plugin counts [with an extensive suite of end-to-end tests](https://github.com/elchininet/custom-sidebar/tree/b080083376cca657bf06d740d3dc30d4fa7c2b32/tests). At the moment of writing, there are 467 tests covering every single option of the plugin and the coverage of the code [is at 100%](https://coveralls.io/github/elchininet/custom-sidebar?branch=master). On top of this, there are also [regression tests through screenshots](https://github.com/elchininet/custom-sidebar/tree/b080083376cca657bf06d740d3dc30d4fa7c2b32/test-snapshots) to check that there are no visual changes when a modification of the code is done. There are also [Nightly Beta Tests](https://github.com/elchininet/custom-sidebar/actions/workflows/ha-beta-tests.yaml) in place that run every night against the [homeassistant/home-assistant:beta tag](https://hub.docker.com/layers/homeassistant/home-assistant/beta/images/) that allows us to detect if any option of the plugin will be broken in the next `Home Assistant` version before that version is released.
9+
This plugin counts [with an extensive suite of end-to-end tests](https://github.com/elchininet/custom-sidebar/tree/b080083376cca657bf06d740d3dc30d4fa7c2b32/tests). At the moment of writing, there are 468 tests covering every single option of the plugin and the coverage of the code [is at 100%](https://coveralls.io/github/elchininet/custom-sidebar?branch=master). On top of this, there are also [regression tests through screenshots](https://github.com/elchininet/custom-sidebar/tree/b080083376cca657bf06d740d3dc30d4fa7c2b32/test-snapshots) to check that there are no visual changes when a modification of the code is done. There are also [Nightly Beta Tests](https://github.com/elchininet/custom-sidebar/actions/workflows/ha-beta-tests.yaml) in place that run every night against the [homeassistant/home-assistant:beta tag](https://hub.docker.com/layers/homeassistant/home-assistant/beta/images/) that allows us to detect if any option of the plugin will be broken in the next `Home Assistant` version before that version is released.
1010

1111
This means that if you detect that your configuration stopped working suddenly after an update, there are four possible reasons for that:
1212

src/utilities/modules/navigate.ts

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,48 @@ import {
88
} from '@constants';
99
import { fireEvent } from './events';
1010

11-
const dispatchLocationChanged = (pathname: string): void => {
12-
fireEvent(
13-
window,
14-
EVENT.LOCATION_CHANGED,
15-
{
16-
replace: pathname
11+
const dispatchLocationChanged = (
12+
replace: boolean,
13+
params: Parameters<typeof window.history.replaceState>
14+
): void => {
15+
16+
const fire = () => {
17+
fireEvent(
18+
window,
19+
EVENT.LOCATION_CHANGED,
20+
{
21+
replace,
22+
source: NAMESPACE
23+
}
24+
);
25+
};
26+
27+
fire();
28+
29+
// If there is another LOCATION_CHANGED event not originated from custom-sidebar
30+
// Within a 100 milliseconds time offset
31+
// Cancel it replacing the location with the previous pathname
32+
const offset = 100;
33+
const time = Date.now();
34+
const callback = (event: Event) => {
35+
const timeDiff = Date.now() - time;
36+
if (
37+
timeDiff < offset &&
38+
// If it is not a custom-sidebar event
39+
(event as CustomEvent).detail?.source !== NAMESPACE
40+
) {
41+
window.history.replaceState(...params);
42+
fire();
1743
}
18-
);
44+
};
45+
46+
// Listen for events during the offset
47+
window.addEventListener(EVENT.LOCATION_CHANGED, callback);
48+
49+
// Cancel the listener after the offset
50+
setTimeout(() => {
51+
window.removeEventListener(EVENT.LOCATION_CHANGED, callback);
52+
}, offset);
1953
};
2054

2155
export const navigate = (
@@ -34,18 +68,16 @@ export const navigate = (
3468
} else {
3569
window.history.pushState(...params);
3670
}
37-
dispatchLocationChanged(pathname);
71+
dispatchLocationChanged(replace, params);
3872
} else {
3973
console.warn(`${NAMESPACE}: ${warningMessage} "${pathname}" as it doesn't start with "/".`);
4074
}
4175
};
4276

4377
export const buildNavigateMethods = (sidebar: HAElement) => {
44-
4578
return {
4679
navigate,
4780
activateItem: async (item: SidebarItem) => {
48-
4981
// Small delay to avoid activating the item before the panel load logic runs
5082
await new Promise((resolve) => setTimeout(resolve, 5));
5183
const activeItem = await sidebar.selector.$.query(`${CUSTOM_ELEMENT.ITEM}.${CLASS.ITEM_SELECTED}`).element as HTMLElement;
@@ -55,7 +87,6 @@ export const buildNavigateMethods = (sidebar: HAElement) => {
5587

5688
item.classList.add(CLASS.ITEM_SELECTED);
5789
item.tabIndex = 0;
58-
5990
}
6091
};
6192
};

tests/10 - javascript-templates-methods.spec.ts

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { expect, test } from 'playwright-test-coverage';
22
import { haConfigRequest } from './ha-services';
33
import {
4+
BASE_URL,
45
CONFIG_FILES,
56
HREFS,
67
SELECTORS
@@ -448,6 +449,65 @@ test.describe('methods in JavaScript templates', () => {
448449

449450
});
450451

452+
test('should not execute a location-changed event not originated from custom-sidebar executed withing a 100 milliseconds offset of a navigate method', async ({ page }) => {
453+
454+
const timeoutOptions = { timeout: 30000 };
455+
const toolsPath = '/config/tools/yaml';
456+
const toolsUrl = `${BASE_URL}${toolsPath}`;
457+
458+
await fulfillJson(
459+
page,
460+
{
461+
order: [
462+
{
463+
...item,
464+
on_click: {
465+
action: 'javascript',
466+
code: `
467+
navigate('${toolsPath}')`
468+
}
469+
}
470+
]
471+
}
472+
);
473+
474+
const goToHomeEvent = async (withDetail: boolean) => {
475+
return page.evaluate((withDetail: boolean) => {
476+
window.history.replaceState(null, '', '/lovelace');
477+
window.dispatchEvent(
478+
new CustomEvent(
479+
'location-changed',
480+
{
481+
bubbles: true,
482+
cancelable: false,
483+
composed: true,
484+
detail: withDetail
485+
? {
486+
replace: true
487+
}
488+
: undefined
489+
}
490+
)
491+
);
492+
}, withDetail);
493+
};
494+
495+
await navigateHome(page);
496+
497+
await getSidebarItem(page, '#').click();
498+
499+
await goToHomeEvent(true);
500+
501+
await expect(page.locator(SELECTORS.PANEL_CONFIG)).toBeVisible(timeoutOptions);
502+
await expect(page).toHaveURL(toolsUrl, timeoutOptions);
503+
504+
await goToHomeEvent(false);
505+
506+
await expect(page.locator(SELECTORS.PANEL_CONFIG)).toBeVisible(timeoutOptions);
507+
await expect(page).toHaveURL(toolsUrl, timeoutOptions);
508+
509+
});
510+
451511
});
452512

453513
test.describe('fireEvent method', () => {

0 commit comments

Comments
 (0)