Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 20 additions & 5 deletions assets/js/components/Loadpoints/BatteryBoostButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<button
class="root position-relative"
tabindex="0"
:class="{ active, belowLimit, full }"
:class="{ active, belowLimit, batteryHold, full }"
:style="{ '--soc': `${adjustedSoc}%` }"
:disabled="disabled"
:aria-label="ariaLabel"
Expand All @@ -17,17 +17,17 @@
<div class="progress-bar bg-primary progress-bar-striped progress-bar-animated"></div>
</div>
<div class="icon-wrapper" :style="iconStyle">
<BatteryBoost :active="active && !belowLimit" />
<BatteryBoost :active="active && available" />
</div>
<div class="icon-wrapper text-white" :style="iconActiveStyle">
<BatteryBoost :active="active && !belowLimit" />
<BatteryBoost :active="active && available" />
</div>
</button>
</template>

<script lang="ts">
import { defineComponent, type PropType } from "vue";
import { CHARGE_MODE, type Timeout } from "@/types/evcc";
import { BATTERY_MODE, CHARGE_MODE, type Timeout } from "@/types/evcc";
import BatteryBoost from "../MaterialIcon/BatteryBoost.vue";
export default defineComponent({
Expand All @@ -40,6 +40,7 @@ export default defineComponent({
batteryBoostLimit: { type: Number, default: 100 },
mode: String as PropType<CHARGE_MODE>,
batterySoc: { type: Number, default: 0 },
batteryMode: String as PropType<BATTERY_MODE>,
},
emits: ["updated", "status"],
data() {
Expand All @@ -66,6 +67,12 @@ export default defineComponent({
belowLimit(): boolean {
return this.batterySoc < this.batteryBoostLimit;
},
batteryHold(): boolean {
return this.batteryMode === BATTERY_MODE.HOLD;
},
available(): boolean {
return !this.belowLimit && !this.batteryHold;
},
iconStyle() {
return {
clipPath: this.active ? `inset(0 0 calc(var(--soc)) 0)` : undefined,
Expand All @@ -76,6 +83,7 @@ export default defineComponent({
},
ariaLabel(): string {
const t = (key: string) => this.$t(`main.loadpointSettings.batteryBoost.${key}`);
if (this.batteryHold) return t("stateHold");
if (this.active) return t("stateActive");
if (this.belowLimit) return t("stateBelowLimit");
return t("stateReady");
Expand Down Expand Up @@ -105,6 +113,12 @@ export default defineComponent({
});
const newValue = !this.active;
// battery hold: only show message, don't toggle
if (newValue && this.batteryHold) {
status("batteryBoostHold");
return;
}
// below limit: only show message, don't toggle
if (newValue && this.belowLimit) {
status("batteryBoostBelowLimit");
Expand Down Expand Up @@ -157,7 +171,8 @@ export default defineComponent({
color: inherit;
opacity: 0.25;
}
.root.belowLimit:not(:disabled) {
.root.belowLimit:not(:disabled),
.root.batteryHold:not(:disabled) {
opacity: 0.5;
}
.root:before,
Expand Down
1 change: 1 addition & 0 deletions assets/js/components/Loadpoints/Loadpoint.vue
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ export default defineComponent({
batteryBoostLimit: { type: Number, default: 100 },
batteryConfigured: Boolean,
batterySoc: Number,
batteryMode: String,

// session
sessionEnergy: Number,
Expand Down
2 changes: 2 additions & 0 deletions assets/js/components/Loadpoints/Loadpoints.vue
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
:pvConfigured="pvConfigured"
:batteryConfigured="batteryConfigured"
:batterySoc="batterySoc"
:batteryMode="batteryMode"
:forecast="forecast"
class="h-100"
:class="{ 'loadpoint-unselected': !selected(loadpoint.id) }"
Expand Down Expand Up @@ -87,6 +88,7 @@ export default defineComponent({
pvConfigured: Boolean,
batteryConfigured: Boolean,
batterySoc: Number,
batteryMode: String,
forecast: Object, // as PropType<Forecast>,
},
emits: ["id-changed"],
Expand Down
1 change: 1 addition & 0 deletions assets/js/components/Site/Site.vue
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
:pvConfigured="pvConfigured"
:batteryConfigured="batteryConfigured"
:batterySoc="batterySoc"
:batteryMode="batteryMode"
:forecast="forecast"
:selectedId="selectedLoadpointId"
@id-changed="selectedLoadpointChanged"
Expand Down
1 change: 1 addition & 0 deletions assets/js/components/Vehicles/Vehicle.vue
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ export default defineComponent({
batteryBoostAvailable: Boolean,
batteryBoostLimit: { type: Number, default: 100 },
batterySoc: Number,
batteryMode: String,
enabled: Boolean,
heating: Boolean,
id: [String, Number],
Expand Down
8 changes: 8 additions & 0 deletions assets/js/types/evcc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ export interface State {
system?: string;
timezone?: string;
battery?: Battery;
batteryMode?: BATTERY_MODE;
pv?: Meter[];
aux?: Meter[];
ext?: Meter[];
Expand Down Expand Up @@ -357,6 +358,13 @@ export enum CHARGE_MODE {
PV = "pv",
}

export enum BATTERY_MODE {
UNKNOWN = "unknown",
NORMAL = "normal",
HOLD = "hold",
CHARGE = "charge",
}

export enum PHASES {
AUTO = 0,
ONE_PHASE = 1,
Expand Down
2 changes: 2 additions & 0 deletions i18n/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -1128,6 +1128,7 @@
"once": "Boost ist für diesen Ladevorgang aktiviert.",
"stateActive": "Batterie Boost aktiv",
"stateBelowLimit": "Batterie zu niedrig für Boost",
"stateHold": "Batterie gesperrt",
"stateReady": "Batterie Boost bereit"
},
"batteryUsage": "Hausbatterie",
Expand Down Expand Up @@ -1237,6 +1238,7 @@
"batteryBoostBelowLimit": "Batterie zu niedrig für Boost.",
"batteryBoostDisabled": "Batterie Boost deaktiviert.",
"batteryBoostEnabled": "Boost bis Batterie bei {limit}.",
"batteryBoostHold": "Batterie gesperrt. Boost nicht verfügbar.",
"charging": "Ladevorgang aktiv …",
"cheapEnergyCharging": "Günstige Energie verfügbar.",
"cheapEnergyNextStart": "Günstige Energie in {duration}.",
Expand Down
2 changes: 2 additions & 0 deletions i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -1128,6 +1128,7 @@
"once": "Boost active for this charging session.",
"stateActive": "Battery boost active",
"stateBelowLimit": "Battery too low for boost",
"stateHold": "Battery locked",
"stateReady": "Battery boost ready"
},
"batteryUsage": "Home Battery",
Expand Down Expand Up @@ -1237,6 +1238,7 @@
"batteryBoostBelowLimit": "Battery too low for boost.",
"batteryBoostDisabled": "Battery boost disabled.",
"batteryBoostEnabled": "Boost until battery at {limit}.",
"batteryBoostHold": "Battery locked. Boost not available.",
"charging": "Charging…",
"cheapEnergyCharging": "Cheap energy available.",
"cheapEnergyNextStart": "Cheap energy in {duration}.",
Expand Down
2 changes: 1 addition & 1 deletion server/mcp/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -1089,7 +1089,7 @@
},
"/loadpoints/{id}/batteryboost/{enable}": {
"post": {
"description": "Enable or disable battery boost. When active, the maximum available home battery power is added until the home battery is drained to configured SoC limit.",
"description": "Enable or disable battery boost. When active, the maximum available home battery power is added until the home battery is drained to configured SoC limit. Note: boost will not work while the battery is on hold (e.g. during fast charging or planned charging with discharge prevention enabled).",
"externalDocs": {
"url": "https://docs.evcc.io/en/docs/features/battery#battery-boost"
},
Expand Down
2 changes: 1 addition & 1 deletion server/mcp/openapi.md
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,7 @@ call removeLoadpointVehicle {

## setLoadpointBatteryBoost

Enable or disable battery boost. When active, the maximum available home battery power is added until the home battery is drained to configured SoC limit.
Enable or disable battery boost. When active, the maximum available home battery power is added until the home battery is drained to configured SoC limit. Note: boost will not work while the battery is on hold (e.g. during fast charging or planned charging with discharge prevention enabled).

**Tags:** loadpoints

Expand Down
2 changes: 1 addition & 1 deletion server/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ paths:
post:
operationId: setLoadpointBatteryBoost
summary: Set battery boost
description: "Enable or disable battery boost. When active, the maximum available home battery power is added until the home battery is drained to configured SoC limit."
description: "Enable or disable battery boost. When active, the maximum available home battery power is added until the home battery is drained to configured SoC limit. Note: boost will not work while the battery is on hold (e.g. during fast charging or planned charging with discharge prevention enabled)."
externalDocs:
url: https://docs.evcc.io/en/docs/features/battery#battery-boost
tags:
Expand Down
20 changes: 20 additions & 0 deletions tests/battery-settings.evcc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ loadpoints:
- title: Carport
charger: charger
mode: now
- title: Garage
charger: charger2
mode: off

chargers:
- name: charger
Expand All @@ -56,6 +59,23 @@ chargers:
source: js
script: |
16
- name: charger2
type: custom
enable:
source: js
script:
enabled:
source: js
script: |
true
status:
source: js
script: |
"C"
maxcurrent:
source: js
script: |
16
tariffs:
currency: EUR
Expand Down
44 changes: 43 additions & 1 deletion tests/boost.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import { test, expect } from "@playwright/test";
import { start, stop, restart, baseUrl } from "./evcc";
import { expectModalHidden, newLoadpoint, addDemoCharger, ChargerStatus } from "./utils";
import {
expectModalHidden,
expectModalVisible,
newLoadpoint,
addDemoCharger,
ChargerStatus,
openTopNavigation,
} from "./utils";
test.use({ baseURL: baseUrl() });

const CONFIG_BATTERY = "battery-settings.evcc.yaml";
Expand All @@ -22,7 +29,7 @@
.click();
await page.getByTestId("loadpoint-settings-button").nth(1).click();
const modal = page.getByTestId("loadpoint-settings-modal");
await modal.getByTestId("battery-boost-limit").selectOption("20 %");

Check failure on line 32 in tests/boost.spec.ts

View workflow job for this annotation

GitHub Actions / Integration

[chromium] › tests/boost.spec.ts:20:3 › boost › activate and deactivate boost in solar mode

1) [chromium] › tests/boost.spec.ts:20:3 › boost › activate and deactivate boost in solar mode ─── Retry #4 ─────────────────────────────────────────────────────────────────────────────────────── Error: locator.selectOption: Error: strict mode violation: getByTestId('loadpoint-settings-modal').getByTestId('battery-boost-limit') resolved to 2 elements: 1) <select data-testid="battery-boost-limit" id="loadpoint_1_batteryBoostLimit" class="form-select form-select-sm">…</select> aka locator('#loadpoint_1_batteryBoostLimit') 2) <select data-testid="battery-boost-limit" id="loadpoint_2_batteryBoostLimit" class="form-select form-select-sm">…</select> aka locator('#loadpoint_2_batteryBoostLimit') Call log: - waiting for getByTestId('loadpoint-settings-modal').getByTestId('battery-boost-limit') 30 | await page.getByTestId("loadpoint-settings-button").nth(1).click(); 31 | const modal = page.getByTestId("loadpoint-settings-modal"); > 32 | await modal.getByTestId("battery-boost-limit").selectOption("20 %"); | ^ 33 | await expect(modal.getByTestId("battery-boost")).toContainText( 34 | "Allow fast charging from home battery until it's drained to 20%." 35 | ); at /home/runner/work/evcc/evcc/tests/boost.spec.ts:32:52

Check failure on line 32 in tests/boost.spec.ts

View workflow job for this annotation

GitHub Actions / Integration

[chromium] › tests/boost.spec.ts:20:3 › boost › activate and deactivate boost in solar mode

1) [chromium] › tests/boost.spec.ts:20:3 › boost › activate and deactivate boost in solar mode ─── Retry #3 ─────────────────────────────────────────────────────────────────────────────────────── Error: locator.selectOption: Error: strict mode violation: getByTestId('loadpoint-settings-modal').getByTestId('battery-boost-limit') resolved to 2 elements: 1) <select data-testid="battery-boost-limit" id="loadpoint_1_batteryBoostLimit" class="form-select form-select-sm">…</select> aka locator('#loadpoint_1_batteryBoostLimit') 2) <select data-testid="battery-boost-limit" id="loadpoint_2_batteryBoostLimit" class="form-select form-select-sm">…</select> aka locator('#loadpoint_2_batteryBoostLimit') Call log: - waiting for getByTestId('loadpoint-settings-modal').getByTestId('battery-boost-limit') 30 | await page.getByTestId("loadpoint-settings-button").nth(1).click(); 31 | const modal = page.getByTestId("loadpoint-settings-modal"); > 32 | await modal.getByTestId("battery-boost-limit").selectOption("20 %"); | ^ 33 | await expect(modal.getByTestId("battery-boost")).toContainText( 34 | "Allow fast charging from home battery until it's drained to 20%." 35 | ); at /home/runner/work/evcc/evcc/tests/boost.spec.ts:32:52

Check failure on line 32 in tests/boost.spec.ts

View workflow job for this annotation

GitHub Actions / Integration

[chromium] › tests/boost.spec.ts:20:3 › boost › activate and deactivate boost in solar mode

1) [chromium] › tests/boost.spec.ts:20:3 › boost › activate and deactivate boost in solar mode ─── Retry #2 ─────────────────────────────────────────────────────────────────────────────────────── Error: locator.selectOption: Error: strict mode violation: getByTestId('loadpoint-settings-modal').getByTestId('battery-boost-limit') resolved to 2 elements: 1) <select data-testid="battery-boost-limit" id="loadpoint_1_batteryBoostLimit" class="form-select form-select-sm">…</select> aka locator('#loadpoint_1_batteryBoostLimit') 2) <select data-testid="battery-boost-limit" id="loadpoint_2_batteryBoostLimit" class="form-select form-select-sm">…</select> aka locator('#loadpoint_2_batteryBoostLimit') Call log: - waiting for getByTestId('loadpoint-settings-modal').getByTestId('battery-boost-limit') 30 | await page.getByTestId("loadpoint-settings-button").nth(1).click(); 31 | const modal = page.getByTestId("loadpoint-settings-modal"); > 32 | await modal.getByTestId("battery-boost-limit").selectOption("20 %"); | ^ 33 | await expect(modal.getByTestId("battery-boost")).toContainText( 34 | "Allow fast charging from home battery until it's drained to 20%." 35 | ); at /home/runner/work/evcc/evcc/tests/boost.spec.ts:32:52

Check failure on line 32 in tests/boost.spec.ts

View workflow job for this annotation

GitHub Actions / Integration

[chromium] › tests/boost.spec.ts:20:3 › boost › activate and deactivate boost in solar mode

1) [chromium] › tests/boost.spec.ts:20:3 › boost › activate and deactivate boost in solar mode ─── Retry #1 ─────────────────────────────────────────────────────────────────────────────────────── Error: locator.selectOption: Error: strict mode violation: getByTestId('loadpoint-settings-modal').getByTestId('battery-boost-limit') resolved to 2 elements: 1) <select data-testid="battery-boost-limit" id="loadpoint_1_batteryBoostLimit" class="form-select form-select-sm">…</select> aka locator('#loadpoint_1_batteryBoostLimit') 2) <select data-testid="battery-boost-limit" id="loadpoint_2_batteryBoostLimit" class="form-select form-select-sm">…</select> aka locator('#loadpoint_2_batteryBoostLimit') Call log: - waiting for getByTestId('loadpoint-settings-modal').getByTestId('battery-boost-limit') 30 | await page.getByTestId("loadpoint-settings-button").nth(1).click(); 31 | const modal = page.getByTestId("loadpoint-settings-modal"); > 32 | await modal.getByTestId("battery-boost-limit").selectOption("20 %"); | ^ 33 | await expect(modal.getByTestId("battery-boost")).toContainText( 34 | "Allow fast charging from home battery until it's drained to 20%." 35 | ); at /home/runner/work/evcc/evcc/tests/boost.spec.ts:32:52

Check failure on line 32 in tests/boost.spec.ts

View workflow job for this annotation

GitHub Actions / Integration

[chromium] › tests/boost.spec.ts:20:3 › boost › activate and deactivate boost in solar mode

1) [chromium] › tests/boost.spec.ts:20:3 › boost › activate and deactivate boost in solar mode ─── Error: locator.selectOption: Error: strict mode violation: getByTestId('loadpoint-settings-modal').getByTestId('battery-boost-limit') resolved to 2 elements: 1) <select data-testid="battery-boost-limit" id="loadpoint_1_batteryBoostLimit" class="form-select form-select-sm">…</select> aka locator('#loadpoint_1_batteryBoostLimit') 2) <select data-testid="battery-boost-limit" id="loadpoint_2_batteryBoostLimit" class="form-select form-select-sm">…</select> aka locator('#loadpoint_2_batteryBoostLimit') Call log: - waiting for getByTestId('loadpoint-settings-modal').getByTestId('battery-boost-limit') 30 | await page.getByTestId("loadpoint-settings-button").nth(1).click(); 31 | const modal = page.getByTestId("loadpoint-settings-modal"); > 32 | await modal.getByTestId("battery-boost-limit").selectOption("20 %"); | ^ 33 | await expect(modal.getByTestId("battery-boost")).toContainText( 34 | "Allow fast charging from home battery until it's drained to 20%." 35 | ); at /home/runner/work/evcc/evcc/tests/boost.spec.ts:32:52
await expect(modal.getByTestId("battery-boost")).toContainText(
"Allow fast charging from home battery until it's drained to 20%."
);
Expand All @@ -49,7 +56,7 @@
.click();
await page.getByTestId("loadpoint-settings-button").nth(1).click();
const modal = page.getByTestId("loadpoint-settings-modal");
await modal.getByTestId("battery-boost-limit").selectOption("90 %");

Check failure on line 59 in tests/boost.spec.ts

View workflow job for this annotation

GitHub Actions / Integration

[chromium] › tests/boost.spec.ts:48:3 › boost › battery too low for boost when limit above soc

2) [chromium] › tests/boost.spec.ts:48:3 › boost › battery too low for boost when limit above soc Retry #4 ─────────────────────────────────────────────────────────────────────────────────────── Error: locator.selectOption: Error: strict mode violation: getByTestId('loadpoint-settings-modal').getByTestId('battery-boost-limit') resolved to 2 elements: 1) <select data-testid="battery-boost-limit" id="loadpoint_1_batteryBoostLimit" class="form-select form-select-sm">…</select> aka locator('#loadpoint_1_batteryBoostLimit') 2) <select data-testid="battery-boost-limit" id="loadpoint_2_batteryBoostLimit" class="form-select form-select-sm">…</select> aka locator('#loadpoint_2_batteryBoostLimit') Call log: - waiting for getByTestId('loadpoint-settings-modal').getByTestId('battery-boost-limit') 57 | await page.getByTestId("loadpoint-settings-button").nth(1).click(); 58 | const modal = page.getByTestId("loadpoint-settings-modal"); > 59 | await modal.getByTestId("battery-boost-limit").selectOption("90 %"); | ^ 60 | await expect(modal.getByTestId("battery-boost")).toContainText("drained to 90%"); 61 | await page.waitForLoadState("networkidle"); 62 | await modal.getByLabel("Close").click(); at /home/runner/work/evcc/evcc/tests/boost.spec.ts:59:52

Check failure on line 59 in tests/boost.spec.ts

View workflow job for this annotation

GitHub Actions / Integration

[chromium] › tests/boost.spec.ts:48:3 › boost › battery too low for boost when limit above soc

2) [chromium] › tests/boost.spec.ts:48:3 › boost › battery too low for boost when limit above soc Retry #3 ─────────────────────────────────────────────────────────────────────────────────────── Error: locator.selectOption: Error: strict mode violation: getByTestId('loadpoint-settings-modal').getByTestId('battery-boost-limit') resolved to 2 elements: 1) <select data-testid="battery-boost-limit" id="loadpoint_1_batteryBoostLimit" class="form-select form-select-sm">…</select> aka locator('#loadpoint_1_batteryBoostLimit') 2) <select data-testid="battery-boost-limit" id="loadpoint_2_batteryBoostLimit" class="form-select form-select-sm">…</select> aka locator('#loadpoint_2_batteryBoostLimit') Call log: - waiting for getByTestId('loadpoint-settings-modal').getByTestId('battery-boost-limit') 57 | await page.getByTestId("loadpoint-settings-button").nth(1).click(); 58 | const modal = page.getByTestId("loadpoint-settings-modal"); > 59 | await modal.getByTestId("battery-boost-limit").selectOption("90 %"); | ^ 60 | await expect(modal.getByTestId("battery-boost")).toContainText("drained to 90%"); 61 | await page.waitForLoadState("networkidle"); 62 | await modal.getByLabel("Close").click(); at /home/runner/work/evcc/evcc/tests/boost.spec.ts:59:52

Check failure on line 59 in tests/boost.spec.ts

View workflow job for this annotation

GitHub Actions / Integration

[chromium] › tests/boost.spec.ts:48:3 › boost › battery too low for boost when limit above soc

2) [chromium] › tests/boost.spec.ts:48:3 › boost › battery too low for boost when limit above soc Retry #2 ─────────────────────────────────────────────────────────────────────────────────────── Error: locator.selectOption: Error: strict mode violation: getByTestId('loadpoint-settings-modal').getByTestId('battery-boost-limit') resolved to 2 elements: 1) <select data-testid="battery-boost-limit" id="loadpoint_1_batteryBoostLimit" class="form-select form-select-sm">…</select> aka locator('#loadpoint_1_batteryBoostLimit') 2) <select data-testid="battery-boost-limit" id="loadpoint_2_batteryBoostLimit" class="form-select form-select-sm">…</select> aka locator('#loadpoint_2_batteryBoostLimit') Call log: - waiting for getByTestId('loadpoint-settings-modal').getByTestId('battery-boost-limit') 57 | await page.getByTestId("loadpoint-settings-button").nth(1).click(); 58 | const modal = page.getByTestId("loadpoint-settings-modal"); > 59 | await modal.getByTestId("battery-boost-limit").selectOption("90 %"); | ^ 60 | await expect(modal.getByTestId("battery-boost")).toContainText("drained to 90%"); 61 | await page.waitForLoadState("networkidle"); 62 | await modal.getByLabel("Close").click(); at /home/runner/work/evcc/evcc/tests/boost.spec.ts:59:52

Check failure on line 59 in tests/boost.spec.ts

View workflow job for this annotation

GitHub Actions / Integration

[chromium] › tests/boost.spec.ts:48:3 › boost › battery too low for boost when limit above soc

2) [chromium] › tests/boost.spec.ts:48:3 › boost › battery too low for boost when limit above soc Retry #1 ─────────────────────────────────────────────────────────────────────────────────────── Error: locator.selectOption: Error: strict mode violation: getByTestId('loadpoint-settings-modal').getByTestId('battery-boost-limit') resolved to 2 elements: 1) <select data-testid="battery-boost-limit" id="loadpoint_1_batteryBoostLimit" class="form-select form-select-sm">…</select> aka locator('#loadpoint_1_batteryBoostLimit') 2) <select data-testid="battery-boost-limit" id="loadpoint_2_batteryBoostLimit" class="form-select form-select-sm">…</select> aka locator('#loadpoint_2_batteryBoostLimit') Call log: - waiting for getByTestId('loadpoint-settings-modal').getByTestId('battery-boost-limit') 57 | await page.getByTestId("loadpoint-settings-button").nth(1).click(); 58 | const modal = page.getByTestId("loadpoint-settings-modal"); > 59 | await modal.getByTestId("battery-boost-limit").selectOption("90 %"); | ^ 60 | await expect(modal.getByTestId("battery-boost")).toContainText("drained to 90%"); 61 | await page.waitForLoadState("networkidle"); 62 | await modal.getByLabel("Close").click(); at /home/runner/work/evcc/evcc/tests/boost.spec.ts:59:52

Check failure on line 59 in tests/boost.spec.ts

View workflow job for this annotation

GitHub Actions / Integration

[chromium] › tests/boost.spec.ts:48:3 › boost › battery too low for boost when limit above soc

2) [chromium] › tests/boost.spec.ts:48:3 › boost › battery too low for boost when limit above soc Error: locator.selectOption: Error: strict mode violation: getByTestId('loadpoint-settings-modal').getByTestId('battery-boost-limit') resolved to 2 elements: 1) <select data-testid="battery-boost-limit" id="loadpoint_1_batteryBoostLimit" class="form-select form-select-sm">…</select> aka locator('#loadpoint_1_batteryBoostLimit') 2) <select data-testid="battery-boost-limit" id="loadpoint_2_batteryBoostLimit" class="form-select form-select-sm">…</select> aka locator('#loadpoint_2_batteryBoostLimit') Call log: - waiting for getByTestId('loadpoint-settings-modal').getByTestId('battery-boost-limit') 57 | await page.getByTestId("loadpoint-settings-button").nth(1).click(); 58 | const modal = page.getByTestId("loadpoint-settings-modal"); > 59 | await modal.getByTestId("battery-boost-limit").selectOption("90 %"); | ^ 60 | await expect(modal.getByTestId("battery-boost")).toContainText("drained to 90%"); 61 | await page.waitForLoadState("networkidle"); 62 | await modal.getByLabel("Close").click(); at /home/runner/work/evcc/evcc/tests/boost.spec.ts:59:52
await expect(modal.getByTestId("battery-boost")).toContainText("drained to 90%");
await page.waitForLoadState("networkidle");
await modal.getByLabel("Close").click();
Expand Down Expand Up @@ -80,6 +87,41 @@
await expect(boostButton).toBeDisabled();
});

test("boost button disabled when battery is on hold", async ({ page }) => {
await start(CONFIG_BATTERY);
await page.goto("/");

// LP1: set solar mode, configure boost limit
const lp1 = page.getByTestId("loadpoint").first();
await lp1.getByTestId("mode").getByRole("button", { name: "Solar", exact: true }).click();
await lp1.getByTestId("loadpoint-settings-button").last().click();
const modal = page.getByTestId("loadpoint-settings-modal").first();
await modal.getByTestId("battery-boost-limit").selectOption("0 %");
await modal.getByLabel("Close").click();
await expectModalHidden(modal);

// enable "Prevent discharge in fast mode"
await openTopNavigation(page);
await page.getByTestId("topnavigation-battery").click();
const batteryModal = page.getByTestId("battery-settings-modal");
await expectModalVisible(batteryModal);
await batteryModal.getByLabel("Prevent discharge in fast mode and planned charging.").check();
await page.getByRole("button", { name: "Close" }).click();
await expectModalHidden(batteryModal);

// LP2: switch to fast mode → triggers global battery hold
const lp2 = page.getByTestId("loadpoint").nth(1);
await lp2.getByTestId("mode").getByRole("button", { name: "Fast" }).click();

// LP1: boost button should show hold state
const boostButton = lp1.getByTestId("battery-boost-button");
await expect(boostButton).toHaveAttribute("aria-label", "Battery locked");

// clicking should not change state
await boostButton.click();
await expect(boostButton).toHaveAttribute("aria-label", "Battery locked");
});

test("boost default for ui-created loadpoint", async ({ page }) => {
await start(CONFIG_BATTERY);

Expand Down
Loading