Config UI: fix duration template param handling (#32572)
This commit is contained in:
parent
6f8a6b8c36
commit
afac7ab56d
14 changed files with 346 additions and 13 deletions
|
|
@ -31,12 +31,12 @@ test("decimal input with german separator", async ({ page }) => {
|
|||
await modal.getByRole("button", { name: "Show advanced settings" }).click();
|
||||
|
||||
// comma accepted as decimal separator
|
||||
const timeout = modal.getByLabel("Timeout");
|
||||
const timeout = modal.getByRole("spinbutton", { name: "Timeout" });
|
||||
await timeout.pressSequentially("0,5");
|
||||
await expect(timeout).toHaveValue("0.5");
|
||||
|
||||
// intermediate zeros survive typing
|
||||
const delay = modal.getByLabel("Delay");
|
||||
const delay = modal.getByRole("spinbutton", { name: "Delay" });
|
||||
await delay.pressSequentially("0.004");
|
||||
await expect(delay).toHaveValue("0.004");
|
||||
await delay.blur();
|
||||
|
|
|
|||
25
tests/config-duration-demo.tpl.yaml
Normal file
25
tests/config-duration-demo.tpl.yaml
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
template: duration-demo
|
||||
group: generic
|
||||
products:
|
||||
- description:
|
||||
generic: Duration Demo Meter
|
||||
params:
|
||||
- name: usage
|
||||
choice: ["grid"]
|
||||
- name: shortduration
|
||||
type: duration
|
||||
default: 30s
|
||||
example: 10s
|
||||
description:
|
||||
generic: Short duration
|
||||
- name: longduration
|
||||
type: duration
|
||||
unit: hour
|
||||
default: 3h
|
||||
description:
|
||||
generic: Long duration
|
||||
render: |
|
||||
type: custom
|
||||
power:
|
||||
source: const
|
||||
value: 0
|
||||
23
tests/config-duration-values.sql
Normal file
23
tests/config-duration-values.sql
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
BEGIN;
|
||||
|
||||
CREATE TABLE `configs` (
|
||||
`id` integer PRIMARY KEY AUTOINCREMENT
|
||||
, `class` integer
|
||||
, `type` text
|
||||
, `title` text
|
||||
, `icon` text
|
||||
, `product` text
|
||||
, `value` text
|
||||
);
|
||||
CREATE TABLE `settings` (
|
||||
`key` text
|
||||
, `value` text
|
||||
, PRIMARY KEY(`key`)
|
||||
);
|
||||
|
||||
-- longduration as duration string (UI-written format), shortduration as legacy nanosecond number
|
||||
INSERT INTO configs(id, class, type, title, icon, product, value) VALUES(1, 2, 'template', 'Duration Test', '', 'Duration Demo Meter', '{"template":"duration-demo","usage":"grid","longduration":"12h","shortduration":15000000000}');
|
||||
|
||||
INSERT INTO settings("key", value) VALUES('gridMeter', 'db:1');
|
||||
|
||||
COMMIT;
|
||||
94
tests/config-duration.spec.ts
Normal file
94
tests/config-duration.spec.ts
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
import { test, expect, type Page, type Locator } from "@playwright/test";
|
||||
import { start, stop, restart, baseUrl } from "./evcc";
|
||||
import { expectModalVisible, expectModalHidden } from "./utils";
|
||||
|
||||
const templateFlags = [
|
||||
"--disable-auth",
|
||||
"--template-type",
|
||||
"meter",
|
||||
"--template",
|
||||
"tests/config-duration-demo.tpl.yaml",
|
||||
];
|
||||
|
||||
test.use({ baseURL: baseUrl() });
|
||||
|
||||
test.afterEach(async () => {
|
||||
await stop();
|
||||
});
|
||||
|
||||
async function openGridMeterModal(page: Page): Promise<Locator> {
|
||||
await page.goto("/#/config");
|
||||
await page.getByTestId("grid").getByRole("button", { name: "edit" }).click();
|
||||
const modal = page.getByTestId("meter-modal");
|
||||
await expectModalVisible(modal);
|
||||
return modal;
|
||||
}
|
||||
|
||||
test.describe("duration fields", async () => {
|
||||
test("template defaults and roundtrip", async ({ page }) => {
|
||||
await start(undefined, undefined, templateFlags);
|
||||
await page.goto("/#/config");
|
||||
await page.getByRole("button", { name: "Add grid meter" }).click();
|
||||
const modal = page.getByTestId("meter-modal");
|
||||
await expectModalVisible(modal);
|
||||
await modal.getByLabel("Manufacturer").selectOption("Duration Demo Meter");
|
||||
|
||||
await expect(modal.getByRole("spinbutton", { name: "Short duration" })).toHaveValue("30");
|
||||
await expect(modal.getByText("Example: 10 seconds", { exact: true })).toBeVisible();
|
||||
await expect(modal.getByLabel("Time unit for Short duration")).toHaveValue("second");
|
||||
await expect(modal.getByRole("spinbutton", { name: "Long duration" })).toHaveValue("3");
|
||||
await expect(modal.getByLabel("Time unit for Long duration")).toHaveValue("hour");
|
||||
|
||||
await modal.getByRole("spinbutton", { name: "Long duration" }).fill("6");
|
||||
await modal.getByRole("button", { name: "Save" }).click();
|
||||
await expectModalHidden(modal);
|
||||
|
||||
await restart(undefined, templateFlags);
|
||||
await page.reload();
|
||||
|
||||
// edited value and untouched default are both stored as duration strings
|
||||
const reopened = await openGridMeterModal(page);
|
||||
await expect(reopened.getByRole("spinbutton", { name: "Long duration" })).toHaveValue("6");
|
||||
await expect(reopened.getByRole("spinbutton", { name: "Short duration" })).toHaveValue("30");
|
||||
});
|
||||
|
||||
test("existing values as string and nanoseconds", async ({ page }) => {
|
||||
await start(undefined, "config-duration-values.sql", templateFlags);
|
||||
|
||||
const modal = await openGridMeterModal(page);
|
||||
await expect(modal.getByRole("spinbutton", { name: "Long duration" })).toHaveValue("12");
|
||||
await expect(modal.getByRole("spinbutton", { name: "Short duration" })).toHaveValue("15");
|
||||
|
||||
await modal.getByRole("button", { name: "Save" }).click();
|
||||
await expectModalHidden(modal);
|
||||
|
||||
await restart(undefined, templateFlags);
|
||||
await page.reload();
|
||||
|
||||
const reopened = await openGridMeterModal(page);
|
||||
await expect(reopened.getByRole("spinbutton", { name: "Long duration" })).toHaveValue("12");
|
||||
await expect(reopened.getByRole("spinbutton", { name: "Short duration" })).toHaveValue("15");
|
||||
});
|
||||
|
||||
test("unit switching keeps number", async ({ page }) => {
|
||||
await start(undefined, "config-duration-values.sql", templateFlags);
|
||||
|
||||
// stored "12h" drives the unit, ns number falls back to template default
|
||||
const modal = await openGridMeterModal(page);
|
||||
await expect(modal.getByLabel("Time unit for Long duration")).toHaveValue("hour");
|
||||
await expect(modal.getByLabel("Time unit for Short duration")).toHaveValue("second");
|
||||
|
||||
await modal.getByLabel("Time unit for Long duration").selectOption("minutes");
|
||||
await expect(modal.getByRole("spinbutton", { name: "Long duration" })).toHaveValue("12");
|
||||
await modal.getByRole("button", { name: "Save" }).click();
|
||||
await expectModalHidden(modal);
|
||||
|
||||
await restart(undefined, templateFlags);
|
||||
await page.reload();
|
||||
|
||||
// stored "12m" restores the selected unit
|
||||
const reopened = await openGridMeterModal(page);
|
||||
await expect(reopened.getByRole("spinbutton", { name: "Long duration" })).toHaveValue("12");
|
||||
await expect(reopened.getByLabel("Time unit for Long duration")).toHaveValue("minute");
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue