diff --git a/src/weather-forecast-card.ts b/src/weather-forecast-card.ts index 16ba5a8..54a7558 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,18 @@ export class WeatherForecastCard extends LitElement { } else { this._hourlyForecastData = hourlyForecastData?.forecast; } + + // Recalculate layout if the number of items changed + const newLength = this.getCurrentForecast().length; + + const oldLength = + (this._currentForecastType === "hourly" + ? oldHourlyLength + : oldDailyLength) ?? 0; + + if (newLength !== oldLength && this._forecastContainer) { + this.layoutForecastItems(this._forecastContainer.clientWidth); + } } private _toggleForecastView(selectedForecast?: ForecastAttribute) { @@ -462,10 +477,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; 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..dac88d1 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 property + 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 property + await waitUntil(() => card._currentItemWidth !== initialWidth); + + // @ts-expect-error: accessing private property + const newWidth = card._currentItemWidth; + + expect(newWidth).toBeDefined(); + expect(newWidth).toBeGreaterThan(initialWidth); + }); });