mirror of
https://github.com/home-assistant/frontend.git
synced 2026-06-05 16:01:46 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| dccad52c07 |
@@ -0,0 +1,73 @@
|
||||
import type { HassServiceTarget } from "home-assistant-js-websocket";
|
||||
import {
|
||||
createQueryString,
|
||||
decodeQueryParams,
|
||||
queryParamsFromServiceTarget,
|
||||
serviceTargetFromQueryParams,
|
||||
type QueryParamConfig,
|
||||
type QueryParamValues,
|
||||
type SearchParamsSource,
|
||||
} from "./query-params";
|
||||
|
||||
export type HistoryLogbookTargetParamKey =
|
||||
| "entity_id"
|
||||
| "label_id"
|
||||
| "floor_id"
|
||||
| "area_id"
|
||||
| "device_id";
|
||||
|
||||
export type HistoryLogbookDateParamKey = "start_date" | "end_date";
|
||||
|
||||
export type HistoryLogbookBooleanParamKey = "back";
|
||||
|
||||
export type HistoryLogbookQueryParams = QueryParamValues<
|
||||
HistoryLogbookTargetParamKey,
|
||||
HistoryLogbookDateParamKey,
|
||||
HistoryLogbookBooleanParamKey
|
||||
>;
|
||||
|
||||
export const historyLogbookTargetParamKeys: HistoryLogbookTargetParamKey[] = [
|
||||
"entity_id",
|
||||
"label_id",
|
||||
"floor_id",
|
||||
"area_id",
|
||||
"device_id",
|
||||
];
|
||||
|
||||
export const historyLogbookQueryParamConfig = {
|
||||
list: historyLogbookTargetParamKeys,
|
||||
date: ["start_date", "end_date"],
|
||||
boolean: [{ key: "back", trueValue: "1" }],
|
||||
} satisfies QueryParamConfig<
|
||||
HistoryLogbookTargetParamKey,
|
||||
HistoryLogbookDateParamKey,
|
||||
HistoryLogbookBooleanParamKey
|
||||
>;
|
||||
|
||||
export const decodeHistoryLogbookQueryParams = (
|
||||
searchParams: SearchParamsSource
|
||||
): HistoryLogbookQueryParams =>
|
||||
decodeQueryParams(searchParams, historyLogbookQueryParamConfig);
|
||||
|
||||
export const historyLogbookTargetFromQueryParams = (
|
||||
params: HistoryLogbookQueryParams
|
||||
): HassServiceTarget | undefined =>
|
||||
serviceTargetFromQueryParams(params, historyLogbookTargetParamKeys);
|
||||
|
||||
export const createHistoryLogbookUrl = (
|
||||
path: string,
|
||||
target: HassServiceTarget,
|
||||
startDate: Date,
|
||||
endDate: Date
|
||||
): string => {
|
||||
const queryString = createQueryString(
|
||||
{
|
||||
...queryParamsFromServiceTarget(target, historyLogbookTargetParamKeys),
|
||||
start_date: startDate,
|
||||
end_date: endDate,
|
||||
},
|
||||
historyLogbookQueryParamConfig
|
||||
);
|
||||
|
||||
return queryString ? `${path}?${queryString}` : path;
|
||||
};
|
||||
@@ -0,0 +1,140 @@
|
||||
import type { HassServiceTarget } from "home-assistant-js-websocket";
|
||||
import { ensureArray } from "../array/ensure-array";
|
||||
|
||||
export type SearchParamsSource =
|
||||
| URLSearchParams
|
||||
| Record<string, string>
|
||||
| string;
|
||||
|
||||
export interface QueryParamConfig<
|
||||
ListKey extends string,
|
||||
DateKey extends string,
|
||||
BooleanKey extends string,
|
||||
> {
|
||||
list?: readonly ListKey[];
|
||||
date?: readonly DateKey[];
|
||||
boolean?: readonly {
|
||||
key: BooleanKey;
|
||||
trueValue: string;
|
||||
}[];
|
||||
}
|
||||
|
||||
export type QueryParamValues<
|
||||
ListKey extends string,
|
||||
DateKey extends string,
|
||||
BooleanKey extends string,
|
||||
> = Partial<
|
||||
Record<ListKey, string[]> &
|
||||
Record<DateKey, Date> &
|
||||
Record<BooleanKey, boolean>
|
||||
>;
|
||||
|
||||
export type ServiceTargetQueryParams<
|
||||
Key extends keyof HassServiceTarget & string,
|
||||
> = Partial<Record<Key, string[]>>;
|
||||
|
||||
const getSearchParam = (
|
||||
searchParams: SearchParamsSource,
|
||||
key: string
|
||||
): string | null => {
|
||||
if (typeof searchParams === "string") {
|
||||
return new URLSearchParams(searchParams).get(key);
|
||||
}
|
||||
if (searchParams instanceof URLSearchParams) {
|
||||
return searchParams.get(key);
|
||||
}
|
||||
return searchParams[key] ?? null;
|
||||
};
|
||||
|
||||
export const decodeQueryParams = <
|
||||
ListKey extends string,
|
||||
DateKey extends string,
|
||||
BooleanKey extends string,
|
||||
>(
|
||||
searchParams: SearchParamsSource,
|
||||
config: QueryParamConfig<ListKey, DateKey, BooleanKey>
|
||||
): QueryParamValues<ListKey, DateKey, BooleanKey> => {
|
||||
const params: QueryParamValues<ListKey, DateKey, BooleanKey> = {};
|
||||
for (const key of config.list ?? []) {
|
||||
const value = getSearchParam(searchParams, key);
|
||||
if (value) {
|
||||
params[key] = value.split(",") as (typeof params)[typeof key];
|
||||
}
|
||||
}
|
||||
for (const key of config.date ?? []) {
|
||||
const value = getSearchParam(searchParams, key);
|
||||
if (value) {
|
||||
params[key] = new Date(value) as (typeof params)[typeof key];
|
||||
}
|
||||
}
|
||||
for (const { key, trueValue } of config.boolean ?? []) {
|
||||
if (getSearchParam(searchParams, key) === trueValue) {
|
||||
params[key] = true as (typeof params)[typeof key];
|
||||
}
|
||||
}
|
||||
return params;
|
||||
};
|
||||
|
||||
export const createQueryString = <
|
||||
ListKey extends string,
|
||||
DateKey extends string,
|
||||
BooleanKey extends string,
|
||||
>(
|
||||
values: QueryParamValues<ListKey, DateKey, BooleanKey>,
|
||||
config: QueryParamConfig<ListKey, DateKey, BooleanKey>
|
||||
): string => {
|
||||
const searchParams = new URLSearchParams();
|
||||
for (const key of config.list ?? []) {
|
||||
const value = values[key] as string[] | undefined;
|
||||
if (value?.length) {
|
||||
searchParams.append(key, value.join(","));
|
||||
}
|
||||
}
|
||||
for (const key of config.date ?? []) {
|
||||
const value = values[key] as Date | undefined;
|
||||
if (value) {
|
||||
searchParams.append(key, value.toISOString());
|
||||
}
|
||||
}
|
||||
for (const { key, trueValue } of config.boolean ?? []) {
|
||||
if (values[key]) {
|
||||
searchParams.append(key, trueValue);
|
||||
}
|
||||
}
|
||||
return searchParams.toString();
|
||||
};
|
||||
|
||||
export const serviceTargetFromQueryParams = <
|
||||
Key extends keyof HassServiceTarget & string,
|
||||
>(
|
||||
params: ServiceTargetQueryParams<Key>,
|
||||
keys: readonly Key[]
|
||||
): HassServiceTarget | undefined => {
|
||||
if (!keys.some((key) => params[key])) {
|
||||
return undefined;
|
||||
}
|
||||
const target: HassServiceTarget = {};
|
||||
for (const key of keys) {
|
||||
const value = params[key];
|
||||
if (value) {
|
||||
target[key] = value;
|
||||
}
|
||||
}
|
||||
return target;
|
||||
};
|
||||
|
||||
export const queryParamsFromServiceTarget = <
|
||||
Key extends keyof HassServiceTarget & string,
|
||||
>(
|
||||
target: HassServiceTarget,
|
||||
keys: readonly Key[]
|
||||
): ServiceTargetQueryParams<Key> => {
|
||||
const params: ServiceTargetQueryParams<Key> = {};
|
||||
for (const key of keys) {
|
||||
const value = target[key];
|
||||
if (value) {
|
||||
params[key] = ensureArray(value);
|
||||
}
|
||||
}
|
||||
return params;
|
||||
};
|
||||
@@ -13,13 +13,16 @@ import type { PropertyValues } from "lit";
|
||||
import { LitElement, css, html } from "lit";
|
||||
import { customElement, property, query, state } from "lit/decorators";
|
||||
import memoizeOne from "memoize-one";
|
||||
import { ensureArray } from "../../common/array/ensure-array";
|
||||
import { storage } from "../../common/decorators/storage";
|
||||
import { computeDomain } from "../../common/entity/compute_domain";
|
||||
import { goBack, navigate } from "../../common/navigate";
|
||||
import { constructUrlCurrentPath } from "../../common/url/construct-url";
|
||||
import {
|
||||
createSearchParam,
|
||||
createHistoryLogbookUrl,
|
||||
decodeHistoryLogbookQueryParams,
|
||||
historyLogbookTargetFromQueryParams,
|
||||
} from "../../common/url/history-logbook-query-params";
|
||||
import {
|
||||
extractSearchParamsObject,
|
||||
removeSearchParam,
|
||||
} from "../../common/url/search-params";
|
||||
@@ -230,43 +233,18 @@ class HaPanelHistory extends LitElement {
|
||||
return;
|
||||
}
|
||||
|
||||
const searchParams = extractSearchParamsObject();
|
||||
const entityIds = searchParams.entity_id;
|
||||
const deviceIds = searchParams.device_id;
|
||||
const areaIds = searchParams.area_id;
|
||||
const floorIds = searchParams.floor_id;
|
||||
const labelsIds = searchParams.label_id;
|
||||
if (entityIds || deviceIds || areaIds || floorIds || labelsIds) {
|
||||
this._targetPickerValue = {};
|
||||
const queryParams = decodeHistoryLogbookQueryParams(
|
||||
extractSearchParamsObject()
|
||||
);
|
||||
const targetPickerValue = historyLogbookTargetFromQueryParams(queryParams);
|
||||
if (targetPickerValue) {
|
||||
this._targetPickerValue = targetPickerValue;
|
||||
}
|
||||
if (entityIds) {
|
||||
const splitIds = entityIds.split(",");
|
||||
this._targetPickerValue!.entity_id = splitIds;
|
||||
if (queryParams.start_date) {
|
||||
this._startDate = queryParams.start_date;
|
||||
}
|
||||
if (deviceIds) {
|
||||
const splitIds = deviceIds.split(",");
|
||||
this._targetPickerValue!.device_id = splitIds;
|
||||
}
|
||||
if (areaIds) {
|
||||
const splitIds = areaIds.split(",");
|
||||
this._targetPickerValue!.area_id = splitIds;
|
||||
}
|
||||
if (floorIds) {
|
||||
const splitIds = floorIds.split(",");
|
||||
this._targetPickerValue!.floor_id = splitIds;
|
||||
}
|
||||
if (labelsIds) {
|
||||
const splitIds = labelsIds.split(",");
|
||||
this._targetPickerValue!.label_id = splitIds;
|
||||
}
|
||||
|
||||
const startDate = searchParams.start_date;
|
||||
if (startDate) {
|
||||
this._startDate = new Date(startDate);
|
||||
}
|
||||
const endDate = searchParams.end_date;
|
||||
if (endDate) {
|
||||
this._endDate = new Date(endDate);
|
||||
if (queryParams.end_date) {
|
||||
this._endDate = queryParams.end_date;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -469,37 +447,15 @@ class HaPanelHistory extends LitElement {
|
||||
}
|
||||
|
||||
private _updatePath() {
|
||||
const params: Record<string, string> = {};
|
||||
|
||||
if (this._targetPickerValue.entity_id) {
|
||||
params.entity_id = ensureArray(this._targetPickerValue.entity_id).join(
|
||||
","
|
||||
);
|
||||
}
|
||||
if (this._targetPickerValue.label_id) {
|
||||
params.label_id = ensureArray(this._targetPickerValue.label_id).join(",");
|
||||
}
|
||||
if (this._targetPickerValue.floor_id) {
|
||||
params.floor_id = ensureArray(this._targetPickerValue.floor_id).join(",");
|
||||
}
|
||||
if (this._targetPickerValue.area_id) {
|
||||
params.area_id = ensureArray(this._targetPickerValue.area_id).join(",");
|
||||
}
|
||||
if (this._targetPickerValue.device_id) {
|
||||
params.device_id = ensureArray(this._targetPickerValue.device_id).join(
|
||||
","
|
||||
);
|
||||
}
|
||||
|
||||
if (this._startDate) {
|
||||
params.start_date = this._startDate.toISOString();
|
||||
}
|
||||
|
||||
if (this._endDate) {
|
||||
params.end_date = this._endDate.toISOString();
|
||||
}
|
||||
|
||||
navigate(`/history?${createSearchParam(params)}`, { replace: true });
|
||||
navigate(
|
||||
createHistoryLogbookUrl(
|
||||
"/history",
|
||||
this._targetPickerValue,
|
||||
this._startDate,
|
||||
this._endDate
|
||||
),
|
||||
{ replace: true }
|
||||
);
|
||||
}
|
||||
|
||||
private async _handleMenuAction(ev: HaDropdownSelectEvent) {
|
||||
|
||||
@@ -4,12 +4,15 @@ import type { PropertyValues } from "lit";
|
||||
import { css, html, LitElement } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import memoizeOne from "memoize-one";
|
||||
import { ensureArray } from "../../common/array/ensure-array";
|
||||
import { storage } from "../../common/decorators/storage";
|
||||
import { goBack, navigate } from "../../common/navigate";
|
||||
import { constructUrlCurrentPath } from "../../common/url/construct-url";
|
||||
import {
|
||||
createSearchParam,
|
||||
createHistoryLogbookUrl,
|
||||
decodeHistoryLogbookQueryParams,
|
||||
historyLogbookTargetFromQueryParams,
|
||||
} from "../../common/url/history-logbook-query-params";
|
||||
import {
|
||||
extractSearchParamsObject,
|
||||
removeSearchParam,
|
||||
} from "../../common/url/search-params";
|
||||
@@ -185,44 +188,17 @@ export class HaPanelLogbook extends LitElement {
|
||||
);
|
||||
|
||||
private _applyURLParams() {
|
||||
const searchParams = extractSearchParamsObject();
|
||||
const entityIds = searchParams.entity_id;
|
||||
const deviceIds = searchParams.device_id;
|
||||
const areaIds = searchParams.area_id;
|
||||
const floorIds = searchParams.floor_id;
|
||||
const labelsIds = searchParams.label_id;
|
||||
if (entityIds || deviceIds || areaIds || floorIds || labelsIds) {
|
||||
this._targetPickerValue = {};
|
||||
}
|
||||
if (entityIds) {
|
||||
const splitIds = entityIds.split(",");
|
||||
this._targetPickerValue!.entity_id = splitIds;
|
||||
}
|
||||
if (deviceIds) {
|
||||
const splitIds = deviceIds.split(",");
|
||||
this._targetPickerValue!.device_id = splitIds;
|
||||
}
|
||||
if (areaIds) {
|
||||
const splitIds = areaIds.split(",");
|
||||
this._targetPickerValue!.area_id = splitIds;
|
||||
}
|
||||
if (floorIds) {
|
||||
const splitIds = floorIds.split(",");
|
||||
this._targetPickerValue!.floor_id = splitIds;
|
||||
}
|
||||
if (labelsIds) {
|
||||
const splitIds = labelsIds.split(",");
|
||||
this._targetPickerValue!.label_id = splitIds;
|
||||
const queryParams = decodeHistoryLogbookQueryParams(
|
||||
extractSearchParamsObject()
|
||||
);
|
||||
const targetPickerValue = historyLogbookTargetFromQueryParams(queryParams);
|
||||
if (targetPickerValue) {
|
||||
this._targetPickerValue = targetPickerValue;
|
||||
}
|
||||
|
||||
const startDateStr = searchParams.start_date;
|
||||
const endDateStr = searchParams.end_date;
|
||||
|
||||
if (startDateStr || endDateStr) {
|
||||
const startDate = startDateStr
|
||||
? new Date(startDateStr)
|
||||
: this._time.range[0];
|
||||
const endDate = endDateStr ? new Date(endDateStr) : this._time.range[1];
|
||||
if (queryParams.start_date || queryParams.end_date) {
|
||||
const startDate = queryParams.start_date ?? this._time.range[0];
|
||||
const endDate = queryParams.end_date ?? this._time.range[1];
|
||||
|
||||
// Only set if date has changed.
|
||||
if (
|
||||
@@ -231,8 +207,8 @@ export class HaPanelLogbook extends LitElement {
|
||||
) {
|
||||
this._time = {
|
||||
range: [
|
||||
startDateStr ? new Date(startDateStr) : this._time.range[0],
|
||||
endDateStr ? new Date(endDateStr) : this._time.range[1],
|
||||
queryParams.start_date ?? this._time.range[0],
|
||||
queryParams.end_date ?? this._time.range[1],
|
||||
],
|
||||
};
|
||||
}
|
||||
@@ -254,37 +230,15 @@ export class HaPanelLogbook extends LitElement {
|
||||
}
|
||||
|
||||
private _updatePath() {
|
||||
const params: Record<string, string> = {};
|
||||
|
||||
if (this._targetPickerValue.entity_id) {
|
||||
params.entity_id = ensureArray(this._targetPickerValue.entity_id).join(
|
||||
","
|
||||
);
|
||||
}
|
||||
if (this._targetPickerValue.label_id) {
|
||||
params.label_id = ensureArray(this._targetPickerValue.label_id).join(",");
|
||||
}
|
||||
if (this._targetPickerValue.floor_id) {
|
||||
params.floor_id = ensureArray(this._targetPickerValue.floor_id).join(",");
|
||||
}
|
||||
if (this._targetPickerValue.area_id) {
|
||||
params.area_id = ensureArray(this._targetPickerValue.area_id).join(",");
|
||||
}
|
||||
if (this._targetPickerValue.device_id) {
|
||||
params.device_id = ensureArray(this._targetPickerValue.device_id).join(
|
||||
","
|
||||
);
|
||||
}
|
||||
|
||||
if (this._time.range[0]) {
|
||||
params.start_date = this._time.range[0].toISOString();
|
||||
}
|
||||
|
||||
if (this._time.range[1]) {
|
||||
params.end_date = this._time.range[1].toISOString();
|
||||
}
|
||||
|
||||
navigate(`/logbook?${createSearchParam(params)}`, { replace: true });
|
||||
navigate(
|
||||
createHistoryLogbookUrl(
|
||||
"/logbook",
|
||||
this._targetPickerValue,
|
||||
this._time.range[0],
|
||||
this._time.range[1]
|
||||
),
|
||||
{ replace: true }
|
||||
);
|
||||
}
|
||||
|
||||
private _refreshLogbook() {
|
||||
|
||||
@@ -296,9 +296,6 @@ export const getMyRedirects = (): Redirects => ({
|
||||
component: "history",
|
||||
redirect: "/history",
|
||||
},
|
||||
maintenance: {
|
||||
redirect: "/maintenance",
|
||||
},
|
||||
overview: {
|
||||
redirect: "/home/overview",
|
||||
},
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import {
|
||||
createHistoryLogbookUrl,
|
||||
decodeHistoryLogbookQueryParams,
|
||||
historyLogbookQueryParamConfig,
|
||||
historyLogbookTargetParamKeys,
|
||||
historyLogbookTargetFromQueryParams,
|
||||
} from "../../../src/common/url/history-logbook-query-params";
|
||||
import {
|
||||
createQueryString,
|
||||
decodeQueryParams,
|
||||
queryParamsFromServiceTarget,
|
||||
serviceTargetFromQueryParams,
|
||||
} from "../../../src/common/url/query-params";
|
||||
|
||||
const panelQueryParams = [
|
||||
{
|
||||
type: "history",
|
||||
path: "/history",
|
||||
},
|
||||
{
|
||||
type: "logbook",
|
||||
path: "/logbook",
|
||||
},
|
||||
] as const;
|
||||
|
||||
describe.each(panelQueryParams)("$type query params", (panel) => {
|
||||
it("decodes target and date params", () => {
|
||||
const params = decodeQueryParams(
|
||||
"?entity_id=light.kitchen,switch.fan&device_id=device-1&area_id=kitchen&floor_id=downstairs&label_id=important&start_date=2026-06-05T10:00:00.000Z&end_date=2026-06-05T11:00:00.000Z&back=1",
|
||||
historyLogbookQueryParamConfig
|
||||
);
|
||||
|
||||
expect(params).toEqual({
|
||||
entity_id: ["light.kitchen", "switch.fan"],
|
||||
label_id: ["important"],
|
||||
floor_id: ["downstairs"],
|
||||
area_id: ["kitchen"],
|
||||
device_id: ["device-1"],
|
||||
start_date: new Date("2026-06-05T10:00:00.000Z"),
|
||||
end_date: new Date("2026-06-05T11:00:00.000Z"),
|
||||
back: true,
|
||||
});
|
||||
});
|
||||
|
||||
it("creates target picker values only when target params are present", () => {
|
||||
expect(
|
||||
serviceTargetFromQueryParams(
|
||||
decodeQueryParams(
|
||||
"?start_date=2026-06-05T10:00:00.000Z",
|
||||
historyLogbookQueryParamConfig
|
||||
),
|
||||
historyLogbookTargetParamKeys
|
||||
)
|
||||
).toBeUndefined();
|
||||
|
||||
expect(
|
||||
serviceTargetFromQueryParams(
|
||||
decodeQueryParams(
|
||||
"?entity_id=light.kitchen&area_id=kitchen",
|
||||
historyLogbookQueryParamConfig
|
||||
),
|
||||
historyLogbookTargetParamKeys
|
||||
)
|
||||
).toEqual({
|
||||
entity_id: ["light.kitchen"],
|
||||
area_id: ["kitchen"],
|
||||
});
|
||||
});
|
||||
|
||||
it("ignores empty target values", () => {
|
||||
expect(
|
||||
serviceTargetFromQueryParams(
|
||||
decodeQueryParams(
|
||||
"?entity_id=&device_id=",
|
||||
historyLogbookQueryParamConfig
|
||||
),
|
||||
historyLogbookTargetParamKeys
|
||||
)
|
||||
).toBeUndefined();
|
||||
});
|
||||
|
||||
it("encodes target picker values", () => {
|
||||
expect(
|
||||
queryParamsFromServiceTarget(
|
||||
{
|
||||
entity_id: ["light.kitchen", "switch.fan"],
|
||||
area_id: "kitchen",
|
||||
},
|
||||
historyLogbookTargetParamKeys
|
||||
)
|
||||
).toEqual({
|
||||
entity_id: ["light.kitchen", "switch.fan"],
|
||||
area_id: ["kitchen"],
|
||||
});
|
||||
});
|
||||
|
||||
it("creates deterministic query strings", () => {
|
||||
expect(
|
||||
createQueryString(
|
||||
{
|
||||
device_id: ["device-1"],
|
||||
entity_id: ["light.kitchen"],
|
||||
start_date: new Date("2026-06-05T10:00:00.000Z"),
|
||||
end_date: new Date("2026-06-05T11:00:00.000Z"),
|
||||
},
|
||||
historyLogbookQueryParamConfig
|
||||
)
|
||||
).toBe(
|
||||
"entity_id=light.kitchen&device_id=device-1&start_date=2026-06-05T10%3A00%3A00.000Z&end_date=2026-06-05T11%3A00%3A00.000Z"
|
||||
);
|
||||
});
|
||||
|
||||
it("creates typed URLs", () => {
|
||||
expect(
|
||||
createHistoryLogbookUrl(
|
||||
panel.path,
|
||||
{ entity_id: ["light.kitchen"] },
|
||||
new Date("2026-06-05T10:00:00.000Z"),
|
||||
new Date("2026-06-05T11:00:00.000Z")
|
||||
)
|
||||
).toBe(
|
||||
`${panel.path}?entity_id=light.kitchen&start_date=2026-06-05T10%3A00%3A00.000Z&end_date=2026-06-05T11%3A00%3A00.000Z`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("history logbook query params", () => {
|
||||
it("decodes query params", () => {
|
||||
expect(
|
||||
decodeHistoryLogbookQueryParams("?entity_id=light.kitchen&back=1")
|
||||
).toEqual({
|
||||
entity_id: ["light.kitchen"],
|
||||
back: true,
|
||||
});
|
||||
});
|
||||
|
||||
it("creates target picker values only when target params are present", () => {
|
||||
expect(
|
||||
historyLogbookTargetFromQueryParams(
|
||||
decodeHistoryLogbookQueryParams("?start_date=2026-06-05T10:00:00.000Z")
|
||||
)
|
||||
).toBeUndefined();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user