chore: fix npm run lint; spaces > tabs for .ts (#21879)

This commit is contained in:
Michael Geers 2025-06-17 17:14:55 +02:00 • committed by GitHub
parent 7c8b9f588e
commit 404c97b654
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
77 changed files with 4813 additions and 4846 deletions

View file

@ -14,6 +14,6 @@ indent_size = 4
[*.css] [*.css]
indent_size = 2 indent_size = 2
[*.{js,html,yml,yaml,json,md}] [*.{js,html,yml,yaml,json,md,ts}]
indent_style = space indent_style = space
indent_size = 2 indent_size = 2

1
.prettierignore Normal file
View file

@ -0,0 +1 @@
tests/custom-css.css

View file

@ -12,9 +12,7 @@ function customParamsSerializer(params: { [key: string]: any }) {
.map((key) => { .map((key) => {
const value = params[key]; const value = params[key];
if (Array.isArray(value)) { if (Array.isArray(value)) {
return value return value.map((v) => `${encodeURIComponent(key)}=${encodeURIComponent(v)}`).join("&");
.map((v) => `${encodeURIComponent(key)}=${encodeURIComponent(v)}`)
.join("&");
} }
return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`; return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
}) })

View file

@ -28,8 +28,7 @@ function createRate(value: number, hoursFromNow: number, durationHours = 1): Rat
const co2Data = { const co2Data = {
rates: [ rates: [
545, 518, 545, 518, 0, 545, 527, 527, 536, 518, 400, 336, 336, 339, 344, 336, 336, 336, 372, 545, 518, 545, 518, 0, 545, 527, 527, 536, 518, 400, 336, 336, 339, 344, 336, 336, 336, 372,
400, 555, 555, 545, 555, 564, 545, 555, 545, 536, 545, 527, 536, 518, 545, 509, 336, 336, 400, 555, 555, 545, 555, 564, 545, 555, 545, 536, 545, 527, 536, 518, 545, 509, 336, 336, 336,
336,
].map((value, i) => createRate(value, i)), ].map((value, i) => createRate(value, i)),
duration: 8695, duration: 8695,
plan: [createRate(213, 4), createRate(336, 11), createRate(336, 12)], plan: [createRate(213, 4), createRate(336, 11), createRate(336, 12)],
@ -70,9 +69,9 @@ const unknownData = {
}; };
const dynamicData = { const dynamicData = {
rates: [ rates: [0.12, 0.15, 0, -0.05, -0.11, -0.24, -0.08, 0.12, 0.25, 0.29, 0.22, 0.31, 0.31, 0.33].map(
0.12, 0.15, 0, -0.05, -0.11, -0.24, -0.08, 0.12, 0.25, 0.29, 0.22, 0.31, 0.31, 0.33, (value, i) => createRate(value, i)
].map((value, i) => createRate(value, i)), ),
duration: 8695, duration: 8695,
plan: [createRate(0.23, 2, 5)], plan: [createRate(0.23, 2, 5)],
smartCostType: "price", smartCostType: "price",

View file

@ -48,8 +48,7 @@ const notificationsData: Notification[] = [
lp: 1, lp: 1,
}, },
{ {
message: message: "vehicle remote charge start: invalid character '<' looking for beginning of value",
"vehicle remote charge start: invalid character '<' looking for beginning of value",
level: "warn", level: "warn",
count: 3, count: 3,
time: timeAgo(4, 2, 0), time: timeAgo(4, 2, 0),

View file

@ -3,8 +3,8 @@ import { describe, expect, test } from "vitest";
import Status from "./Status.vue"; import Status from "./Status.vue";
import { CURRENCY } from "@/types/evcc"; import { CURRENCY } from "@/types/evcc";
const serializeData = (data: Object) => (data ? `:${JSON.stringify(data)}` : ""); const serializeData = (data: object) => (data ? `:${JSON.stringify(data)}` : "");
config.global.mocks["$t"] = (key: string, data: Object) => `${key}${serializeData(data)}`; config.global.mocks["$t"] = (key: string, data: object) => `${key}${serializeData(data)}`;
config.global.mocks["$i18n"] = { locale: "de-DE" }; config.global.mocks["$i18n"] = { locale: "de-DE" };
const allEntries = { const allEntries = {
@ -19,7 +19,7 @@ const allEntries = {
planstart: false, planstart: false,
}; };
const expectEntries = (props: InstanceType<typeof Status>["$props"], entries: Object) => { const expectEntries = (props: InstanceType<typeof Status>["$props"], entries: object) => {
const expectedEntries = { ...allEntries, ...entries }; const expectedEntries = { ...allEntries, ...entries };
const wrapper = mount(Status, { props }); const wrapper = mount(Status, { props });
@ -49,10 +49,7 @@ describe("basics", () => {
); );
}); });
test("vehicle is charging", () => { test("vehicle is charging", () => {
expectEntries( expectEntries({ connected: true, charging: true }, { charger: "main.vehicleStatus.charging" });
{ connected: true, charging: true },
{ charger: "main.vehicleStatus.charging" }
);
}); });
}); });

View file

@ -53,7 +53,7 @@ export function removeLocalePreference(i18n: VueI18nInstance) {
} }
export function setLocalePreference(i18n: VueI18nInstance, locale: typeof i18n.locale) { export function setLocalePreference(i18n: VueI18nInstance, locale: typeof i18n.locale) {
if (!LOCALES.hasOwnProperty(locale)) { if (!(locale in LOCALES)) {
console.error("unknown locale", locale); console.error("unknown locale", locale);
return; return;
} }

View file

@ -5,7 +5,7 @@ export default defineComponent({
methods: { methods: {
// collect all target component properties from current instance // collect all target component properties from current instance
collectProps(component: any, state?: State) { collectProps(component: any, state?: State) {
let data: Record<string, any> = {}; const data: Record<string, any> = {};
for (const prop in component.props) { for (const prop in component.props) {
const p = prop as keyof State; const p = prop as keyof State;
// check in optional state // check in optional state

View file

@ -12,8 +12,10 @@ config.global.mocks["$t"] = (a: string) => a;
const fmt = mount( const fmt = mount(
defineComponent({ defineComponent({
render() {},
mixins: [formatter], mixins: [formatter],
render() {
return null;
},
}) })
).vm; ).vm;

View file

@ -77,9 +77,7 @@ export default defineComponent({
} }
if (d === undefined) { if (d === undefined) {
d = d =
POWER_UNIT.KW === unit || POWER_UNIT.KW === unit || POWER_UNIT.MW === unit || (POWER_UNIT.W !== unit && 0 === watt)
POWER_UNIT.MW === unit ||
(POWER_UNIT.W !== unit && 0 === watt)
? 1 ? 1
: 0; : 0;
} }

View file

@ -4,7 +4,8 @@ import pluginVue from "eslint-plugin-vue";
import { defineConfigWithVueTs, vueTsConfigs } from "@vue/eslint-config-typescript"; import { defineConfigWithVueTs, vueTsConfigs } from "@vue/eslint-config-typescript";
import skipFormattingConfig from "@vue/eslint-config-prettier/skip-formatting"; import skipFormattingConfig from "@vue/eslint-config-prettier/skip-formatting";
export default defineConfigWithVueTs( export default [
...defineConfigWithVueTs(
js.configs.recommended, js.configs.recommended,
...pluginVue.configs["flat/recommended"], ...pluginVue.configs["flat/recommended"],
vueTsConfigs.recommended, vueTsConfigs.recommended,
@ -31,4 +32,8 @@ export default defineConfigWithVueTs(
"@typescript-eslint/no-explicit-any": "off", "@typescript-eslint/no-explicit-any": "off",
}, },
} }
); ).map((config) => ({
...config,
files: ["assets/**/*.{ts,js,vue}", "tests/**/*.ts"],
})),
];

View file

@ -5,8 +5,10 @@
"scripts": { "scripts": {
"build": "vite build", "build": "vite build",
"test": "cross-env TZ=Europe/Berlin vitest", "test": "cross-env TZ=Europe/Berlin vitest",
"lint": "prettier assets ./**/*.{yml,yaml,sh} ./i18n/*.json --write && eslint assets/**/*.js assets/**/*.vue --fix --max-warnings=0 && npm run tsc", "lint": "npm run lint:prettier && npm run lint:eslint && npm run lint:tsc",
"tsc": "vue-tsc --noEmit", "lint:prettier": "prettier assets tests **/*.{yaml,sh} i18n/*.json --write",
"lint:eslint": "eslint --fix --max-warnings=0",
"lint:tsc": "vue-tsc --noEmit",
"dev": "vite", "dev": "vite",
"playwright": "playwright test --ui", "playwright": "playwright test --ui",
"simulator": "vite tests/simulator", "simulator": "vite tests/simulator",

View file

@ -29,9 +29,7 @@ test.describe("battery meter", async () => {
await meterModal.getByLabel("Manufacturer").selectOption("Demo battery"); await meterModal.getByLabel("Manufacturer").selectOption("Demo battery");
await meterModal.getByLabel("Power").fill("4000"); await meterModal.getByLabel("Power").fill("4000");
await meterModal.getByLabel("Charge").fill("80"); await meterModal.getByLabel("Charge").fill("80");
await expect(meterModal.getByLabel("Maximum AC power of the hybrid inverter")).toHaveCount( await expect(meterModal.getByLabel("Maximum AC power of the hybrid inverter")).toHaveCount(0);
0
);
await expect(meterModal.getByRole("button", { name: "Validate & save" })).toBeVisible(); await expect(meterModal.getByRole("button", { name: "Validate & save" })).toBeVisible();
await meterModal.getByRole("link", { name: "validate" }).click(); await meterModal.getByRole("link", { name: "validate" }).click();
await expect(meterModal.getByTestId("device-tag-power")).toContainText("4.0 kW"); await expect(meterModal.getByTestId("device-tag-power")).toContainText("4.0 kW");

View file

@ -246,9 +246,7 @@ test.describe("loadpoint", async () => {
await page.getByTestId("loadpoint").nth(0).getByRole("button", { name: "edit" }).click(); await page.getByTestId("loadpoint").nth(0).getByRole("button", { name: "edit" }).click();
await expectModalVisible(lpModal); await expectModalVisible(lpModal);
await expect(lpModal.getByTestId("loadpointPollMode-charging")).toHaveClass(/active/); await expect(lpModal.getByTestId("loadpointPollMode-charging")).toHaveClass(/active/);
await expect( await expect(lpModal.getByRole("checkbox", { name: "Interpolate charge level" })).toBeChecked();
lpModal.getByRole("checkbox", { name: "Interpolate charge level" })
).toBeChecked();
await lpModal.getByLabel("Default vehicle").selectOption(VEHICLE_1); await lpModal.getByLabel("Default vehicle").selectOption(VEHICLE_1);
await lpModal.getByRole("button", { name: "Save" }).click(); await lpModal.getByRole("button", { name: "Save" }).click();
await expectModalHidden(lpModal); await expectModalHidden(lpModal);
@ -265,15 +263,9 @@ test.describe("loadpoint", async () => {
// check loadpoint default vehicles // check loadpoint default vehicles
for (const [index, vehicle] of [VEHICLE_1, VEHICLE_2].entries()) { for (const [index, vehicle] of [VEHICLE_1, VEHICLE_2].entries()) {
await page await page.getByTestId("loadpoint").nth(index).getByRole("button", { name: "edit" }).click();
.getByTestId("loadpoint")
.nth(index)
.getByRole("button", { name: "edit" })
.click();
await expectModalVisible(lpModal); await expectModalVisible(lpModal);
await expect(lpModal.locator("#loadpointParamVehicle option:checked")).toHaveText( await expect(lpModal.locator("#loadpointParamVehicle option:checked")).toHaveText(vehicle);
vehicle
);
await lpModal.getByRole("button", { name: "Close" }).click(); await lpModal.getByRole("button", { name: "Close" }).click();
await expectModalHidden(lpModal); await expectModalHidden(lpModal);
} }
@ -307,9 +299,7 @@ test.describe("loadpoint", async () => {
await page.getByRole("button", { name: "Solar", exact: true }).click(); await page.getByRole("button", { name: "Solar", exact: true }).click();
await restart(CONFIG_EMPTY); await restart(CONFIG_EMPTY);
await page.reload(); await page.reload();
await expect(page.getByRole("button", { name: "Solar", exact: true })).toHaveClass( await expect(page.getByRole("button", { name: "Solar", exact: true })).toHaveClass(/active/);
/active/
);
// change default mode in config to fast // change default mode in config to fast
await page.goto("/#/config"); await page.goto("/#/config");
@ -498,9 +488,7 @@ power:
await lpEntry.getByRole("button", { name: "edit" }).click(); await lpEntry.getByRole("button", { name: "edit" }).click();
await expectModalVisible(lpModal); await expectModalVisible(lpModal);
await expect(lpModal.getByLabel("Charger").first()).toHaveValue( await expect(lpModal.getByLabel("Charger").first()).toHaveValue("User-defined device [db:1]");
"User-defined device [db:1]"
);
await lpModal.getByLabel("Charger").first().click(); await lpModal.getByLabel("Charger").first().click();
await expectModalVisible(chargerModal); await expectModalVisible(chargerModal);

View file

@ -30,10 +30,7 @@ test.describe("mqtt", async () => {
test.beforeAll(async () => { test.beforeAll(async () => {
mqttReachable = await isMqttReachable(VALID_BROKER, VALID_USERNAME, VALID_PASSWORD); mqttReachable = await isMqttReachable(VALID_BROKER, VALID_USERNAME, VALID_PASSWORD);
}); });
test.skip( test.skip(!mqttReachable, `MQTT broker ${VALID_BROKER} is not reachable, skipping tests`);
!mqttReachable,
`MQTT broker ${VALID_BROKER} is not reachable, skipping tests`
);
test("mqtt not configured", async ({ page }) => { test("mqtt not configured", async ({ page }) => {
await expect(page.getByTestId("mqtt")).toBeVisible(); await expect(page.getByTestId("mqtt")).toBeVisible();

View file

@ -31,9 +31,7 @@ test.describe("pv meter", async () => {
await meterModal.getByLabel("Power optional").fill("5000"); await meterModal.getByLabel("Power optional").fill("5000");
await page.getByRole("button", { name: "Show advanced settings" }).click(); await page.getByRole("button", { name: "Show advanced settings" }).click();
await expect(meterModal.getByLabel("Minimum charge")).not.toBeVisible(); // battery usage only await expect(meterModal.getByLabel("Minimum charge")).not.toBeVisible(); // battery usage only
await expect( await expect(meterModal.getByLabel("Maximum AC power of the hybrid inverter")).toBeVisible(); // pv usage only
meterModal.getByLabel("Maximum AC power of the hybrid inverter")
).toBeVisible(); // pv usage only
await expect(meterModal.getByRole("button", { name: "Validate & save" })).toBeVisible(); await expect(meterModal.getByRole("button", { name: "Validate & save" })).toBeVisible();
await meterModal.getByRole("link", { name: "validate" }).click(); await meterModal.getByRole("link", { name: "validate" }).click();
await expect(meterModal.getByTestId("device-tag-power")).toContainText("5.0 kW"); await expect(meterModal.getByTestId("device-tag-power")).toContainText("5.0 kW");

View file

@ -158,10 +158,7 @@ test.describe("vehicle variations", async () => {
.selectOption("Vehicle no SoC with Capacity"); .selectOption("Vehicle no SoC with Capacity");
// kWh based limit // kWh based limit
await lp1 await lp1.getByTestId("limit-energy").getByRole("combobox").selectOption("50 kWh (+50%)");
.getByTestId("limit-energy")
.getByRole("combobox")
.selectOption("50 kWh (+50%)");
// kWh based plan // kWh based plan
await setAndVerifyPlan(page, lp1, { energy: "25 kWh" }); await setAndVerifyPlan(page, lp1, { energy: "25 kWh" });
@ -383,11 +380,7 @@ test.describe("repeating", async () => {
await expect(modal.getByTestId("plan-entry").last()).toContainText("#2"); await expect(modal.getByTestId("plan-entry").last()).toContainText("#2");
// remove plan // remove plan
await modal await modal.getByTestId("plan-entry").last().getByRole("button", { name: "Remove" }).click();
.getByTestId("plan-entry")
.last()
.getByRole("button", { name: "Remove" })
.click();
await expect(modal.getByTestId("plan-entry")).toHaveCount(1); await expect(modal.getByTestId("plan-entry")).toHaveCount(1);
await expect(modal.getByTestId("plan-entry").first()).not.toContainText("#1"); await expect(modal.getByTestId("plan-entry").first()).not.toContainText("#1");
}); });
@ -479,9 +472,7 @@ test.describe("repeating", async () => {
// select none // select none
await modal.getByRole("checkbox", { name: "Select all" }).click(); await modal.getByRole("checkbox", { name: "Select all" }).click();
await expect(modal.getByTestId("repeating-plan-weekdays").getByRole("button")).toHaveText( await expect(modal.getByTestId("repeating-plan-weekdays").getByRole("button")).toHaveText("–");
"–"
);
// select specific weekdays // select specific weekdays
await modal.getByRole("checkbox", { name: "Thursday" }).check(); await modal.getByRole("checkbox", { name: "Thursday" }).check();
@ -613,10 +604,7 @@ test.describe("repeating", async () => {
.locator("select") .locator("select")
.selectOption("Vehicle with SoC with Capacity"); .selectOption("Vehicle with SoC with Capacity");
await lp1 await lp1.getByTestId("charging-plan").getByRole("button", { name: "tomorrow 09:20" }).click();
.getByTestId("charging-plan")
.getByRole("button", { name: "tomorrow 09:20" })
.click();
modal = await page.getByTestId("charging-plan-modal"); modal = await page.getByTestId("charging-plan-modal");
await expect(modal.getByTestId("plan-entry")).toHaveCount(2); await expect(modal.getByTestId("plan-entry")).toHaveCount(2);
await expect(modal.getByTestId("plan-preview-title")).toHaveText("Next plan #2"); await expect(modal.getByTestId("plan-preview-title")).toHaveText("Next plan #2");

View file

@ -71,9 +71,7 @@ test.describe("basics", async () => {
await expect(page.getByTestId("sessions-foot-avgPrice")).toBeVisible(); await expect(page.getByTestId("sessions-foot-avgPrice")).toBeVisible();
await expect(page.getByTestId("sessions-foot-avgPrice")).toHaveText("27.5"); await expect(page.getByTestId("sessions-foot-avgPrice")).toHaveText("27.5");
await expect(page.getByTestId("sessions-head-chargeDuration")).toContainText( await expect(page.getByTestId("sessions-head-chargeDuration")).toContainText("Durationh:mm");
"Durationh:mm"
);
await expect(page.getByTestId("sessions-foot-chargeDuration")).toBeVisible(); await expect(page.getByTestId("sessions-foot-chargeDuration")).toBeVisible();
await expect(page.getByTestId("sessions-foot-chargeDuration")).toHaveText("1:30"); await expect(page.getByTestId("sessions-foot-chargeDuration")).toHaveText("1:30");
@ -294,9 +292,10 @@ test.describe("csv export", async () => {
// current month // current month
await page.goto(`/#/sessions`); await page.goto(`/#/sessions`);
await expect( await expect(page.getByRole("link", { name: `Download ${MONTH_YEAR} CSV` })).toHaveAttribute(
page.getByRole("link", { name: `Download ${MONTH_YEAR} CSV` }) "href",
).toHaveAttribute("href", `./api/sessions?format=csv&lang=en&year=${YEAR}&month=${MONTH}`); `./api/sessions?format=csv&lang=en&year=${YEAR}&month=${MONTH}`
);
}); });
}); });

View file

@ -1,6 +1,5 @@
<!doctype html> <!doctype html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
@ -11,5 +10,4 @@
<div id="app"></div> <div id="app"></div>
<script type="module" src="./src/main.js"></script> <script type="module" src="./src/main.js"></script>
</body> </body>
</html> </html>