From 842a3e6bca4b204009941b2b8e767bf1146eb011 Mon Sep 17 00:00:00 2001 From: troinine Date: Fri, 19 Dec 2025 17:32:17 +0200 Subject: [PATCH 1/5] fix: recalculate item width when number of forecast changes --- src/weather-forecast-card.ts | 16 ++++++++++++++ test/mocks/hass.ts | 14 +++++++++--- test/weather-forecast-card.test.ts | 35 +++++++++++++++++++++++++++++- 3 files changed, 61 insertions(+), 4 deletions(-) diff --git a/src/weather-forecast-card.ts b/src/weather-forecast-card.ts index 16ba5a8..85b896f 100644 --- a/src/weather-forecast-card.ts +++ b/src/weather-forecast-card.ts @@ -304,6 +304,9 @@ export class WeatherForecastCard extends LitElement { return; } + const oldHourlyLength = this._hourlyForecastData?.length; + const oldDailyLength = this._dailyForecastData?.length; + const hourlyForecastData = getForecast( attributes, this._hourlyForecastEvent, @@ -330,6 +333,19 @@ export class WeatherForecastCard extends LitElement { } else { this._hourlyForecastData = hourlyForecastData?.forecast; } + + // Recalculate layout if the number of items changed + const newLength = + this._currentForecastType === "hourly" + ? this._hourlyForecastData?.length + : this._dailyForecastData?.length; + + const oldLength = + this._currentForecastType === "hourly" ? oldHourlyLength : oldDailyLength; + + if (newLength !== oldLength && this._forecastContainer) { + this.layoutForecastItems(this._forecastContainer.clientWidth); + } } private _toggleForecastView(selectedForecast?: ForecastAttribute) { diff --git a/test/mocks/hass.ts b/test/mocks/hass.ts index d22d4f5..638d54d 100644 --- a/test/mocks/hass.ts +++ b/test/mocks/hass.ts @@ -316,9 +316,17 @@ export class MockHass { } // Update forecast data for all subscriptions - updateForecasts() { - this.subscriptions.forEach((callback, id) => { - console.log(`Updating subscription ${id}`); + updateForecasts(type: "hourly" | "daily") { + this.subscriptions.forEach((callback) => { + const mockForecast = + type === "hourly" ? this.hourlyForecast : this.dailyForecast; + + const forecastEvent: ForecastEvent = { + type, + forecast: mockForecast as [ForecastAttribute], + }; + + callback(forecastEvent); }); } } diff --git a/test/weather-forecast-card.test.ts b/test/weather-forecast-card.test.ts index fcd19c1..f57f804 100644 --- a/test/weather-forecast-card.test.ts +++ b/test/weather-forecast-card.test.ts @@ -1,5 +1,5 @@ import { beforeEach, describe, expect, it } from "vitest"; -import { fixture } from "@open-wc/testing"; +import { fixture, waitUntil } from "@open-wc/testing"; import { html } from "lit"; import { MockHass } from "./mocks/hass"; import { WeatherForecastCard } from "../src/weather-forecast-card"; @@ -100,4 +100,37 @@ describe("weather-forecast-card", () => { expect(elConditionState?.textContent.trim()).toBe("Sunny"); }); + + it("should recalculate layout if forecast item count changes", async () => { + const container = card.shadowRoot!.querySelector( + ".wfc-forecast-container" + ) as HTMLElement; + + Object.defineProperty(container, "clientWidth", { + value: 350, + configurable: true, + }); + + await card.updateComplete; + + // @ts-expect-error: accessing private method + await waitUntil(() => card._currentItemWidth > 0); + + // @ts-expect-error: accessing private property + const initialWidth = card._currentItemWidth; + + const shortForecast = TEST_FORECAST_DAILY.slice(0, 3); + mockHassInstance.dailyForecast = shortForecast; + + mockHassInstance.updateForecasts("daily"); + + // @ts-expect-error: accessing private method + await waitUntil(() => card._currentItemWidth !== initialWidth); + + // @ts-expect-error: accessing private property + const newWidth = card._currentItemWidth; + + expect(newWidth).toBeDefined(); + expect(newWidth).toBeGreaterThan(initialWidth); + }); }); From 266b17c86827f0e96d0bf577b110cec09fad4f63 Mon Sep 17 00:00:00 2001 From: troinine Date: Fri, 19 Dec 2025 17:55:40 +0200 Subject: [PATCH 2/5] fix: review fixes --- src/weather-forecast-card.ts | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/weather-forecast-card.ts b/src/weather-forecast-card.ts index 85b896f..bd9591d 100644 --- a/src/weather-forecast-card.ts +++ b/src/weather-forecast-card.ts @@ -335,10 +335,7 @@ export class WeatherForecastCard extends LitElement { } // Recalculate layout if the number of items changed - const newLength = - this._currentForecastType === "hourly" - ? this._hourlyForecastData?.length - : this._dailyForecastData?.length; + const newLength = this.getCurrentForecast().length; const oldLength = this._currentForecastType === "hourly" ? oldHourlyLength : oldDailyLength; @@ -478,10 +475,7 @@ export class WeatherForecastCard extends LitElement { private layoutForecastItems(containerWidth: number) { if (containerWidth <= 0 || !this._minForecastItemWidth) return; - const items = - (this._currentForecastType === "hourly" - ? this._hourlyForecastEvent?.forecast - : this._dailyForecastEvent?.forecast) || []; + const items = this.getCurrentForecast(); if (!items.length) return; From 6e7fc34872bbc79f520a1a3f61c7b7f1ffaa4441 Mon Sep 17 00:00:00 2001 From: Tero Roininen Date: Fri, 19 Dec 2025 18:03:24 +0200 Subject: [PATCH 3/5] fix: avoid unnecessary renders Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Tero Roininen --- src/weather-forecast-card.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/weather-forecast-card.ts b/src/weather-forecast-card.ts index bd9591d..54a7558 100644 --- a/src/weather-forecast-card.ts +++ b/src/weather-forecast-card.ts @@ -338,7 +338,9 @@ export class WeatherForecastCard extends LitElement { const newLength = this.getCurrentForecast().length; const oldLength = - this._currentForecastType === "hourly" ? oldHourlyLength : oldDailyLength; + (this._currentForecastType === "hourly" + ? oldHourlyLength + : oldDailyLength) ?? 0; if (newLength !== oldLength && this._forecastContainer) { this.layoutForecastItems(this._forecastContainer.clientWidth); From c410b57613f09ff8b10a37e064efae056c70e9d9 Mon Sep 17 00:00:00 2001 From: Tero Roininen Date: Fri, 19 Dec 2025 18:03:51 +0200 Subject: [PATCH 4/5] fix: review fix Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Tero Roininen --- test/weather-forecast-card.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/weather-forecast-card.test.ts b/test/weather-forecast-card.test.ts index f57f804..31e2fd2 100644 --- a/test/weather-forecast-card.test.ts +++ b/test/weather-forecast-card.test.ts @@ -113,7 +113,7 @@ describe("weather-forecast-card", () => { await card.updateComplete; - // @ts-expect-error: accessing private method + // @ts-expect-error: accessing private property await waitUntil(() => card._currentItemWidth > 0); // @ts-expect-error: accessing private property From 7e0527b9adbf9f7b34153ace4a85d2867f490df4 Mon Sep 17 00:00:00 2001 From: Tero Roininen Date: Fri, 19 Dec 2025 18:04:07 +0200 Subject: [PATCH 5/5] fix: review fix Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Tero Roininen --- test/weather-forecast-card.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/weather-forecast-card.test.ts b/test/weather-forecast-card.test.ts index 31e2fd2..dac88d1 100644 --- a/test/weather-forecast-card.test.ts +++ b/test/weather-forecast-card.test.ts @@ -124,7 +124,7 @@ describe("weather-forecast-card", () => { mockHassInstance.updateForecasts("daily"); - // @ts-expect-error: accessing private method + // @ts-expect-error: accessing private property await waitUntil(() => card._currentItemWidth !== initialWidth); // @ts-expect-error: accessing private property