chore: fix flaky sponsor and ext meter order tests (#30567)

This commit is contained in:
Michael Geers 2026-06-06 17:22:52 +02:00 • committed by GitHub
parent ead9296337
commit abc66802ad
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 47 additions and 10 deletions

View file

@ -198,8 +198,8 @@ test.describe("ext meter order", async () => {
// Restart and check order is preserved in both UIs // Restart and check order is preserved in both UIs
await restart(CONFIG_BASICS); await restart(CONFIG_BASICS);
// Check config UI // Check config UI, reload to reconnect websocket
await page.goto("/#/config"); await page.reload();
await expect(extMeters).toHaveCount(3); await expect(extMeters).toHaveCount(3);
await expect(extMeters.nth(0)).toContainText("Meter 1"); await expect(extMeters.nth(0)).toContainText("Meter 1");
await expect(extMeters.nth(1)).toContainText("Meter 2"); await expect(extMeters.nth(1)).toContainText("Meter 2");

View file

@ -17,7 +17,7 @@ test.afterEach(async () => {
await stop(); await stop();
}); });
const REDACT_CONFIG = "sponsor.evcc.yaml"; const REDACT_CONFIG = "redact.evcc.yaml";
const CONFIG = "issue.evcc.yaml"; const CONFIG = "issue.evcc.yaml";
test.describe("issue creation", () => { test.describe("issue creation", () => {

26
tests/redact.evcc.yaml Normal file
View file

@ -0,0 +1,26 @@
# expired sponsor token
sponsortoken: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJldmNjLmlvIiwic3ViIjoidHJpYWwiLCJleHAiOjE3NTQ5OTI4MDAsImlhdCI6MTc1MzY5NjgwMCwic3BlIjp0cnVlLCJzcmMiOiJtYSJ9.XKa5DHT-icCM9awcX4eS8feW0J_KIjsx2IxjcRRQOcQ
site:
title: Redact Test
meters:
pv: shelly_pv
loadpoints:
- title: Carport
charger: charger
chargers:
- name: charger
type: template
template: demo-charger
meters:
# local device with credentials to verify redaction
- name: shelly_pv
type: template
template: shelly-1pm
usage: pv
host: localhost
user: test@example.org
password: none

View file

@ -6,12 +6,14 @@ site:
loadpoints: loadpoints:
- title: Carport - title: Carport
charger: easee_charger charger: alfen_charger
chargers: chargers:
- name: easee_charger # sponsorship-required charger without cloud communication
- name: alfen_charger
type: template type: template
template: easee template: alfen
user: test@example.org modbus: tcpip
password: none host: localhost
charger: EH123456 port: 502
id: 1

View file

@ -20,7 +20,7 @@ CREATE TABLE `configs` (
INSERT INTO settings("key", value) VALUES('sponsorToken', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJldmNjLmlvIiwic3ViIjoidHJpYWwiLCJleHAiOjE3NTQ5OTI4MDAsImlhdCI6MTc1MzY5NjgwMCwic3BlIjp0cnVlLCJzcmMiOiJtYSJ9.XKa5DHT-icCM9awcX4eS8feW0J_KIjsx2IxjcRRQOcQ'); INSERT INTO settings("key", value) VALUES('sponsorToken', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJldmNjLmlvIiwic3ViIjoidHJpYWwiLCJleHAiOjE3NTQ5OTI4MDAsImlhdCI6MTc1MzY5NjgwMCwic3BlIjp0cnVlLCJzcmMiOiJtYSJ9.XKa5DHT-icCM9awcX4eS8feW0J_KIjsx2IxjcRRQOcQ');
-- loadpoint with charger that requires sponsorship -- loadpoint with charger that requires sponsorship
INSERT INTO configs(id, class, type, title, icon, product, value) VALUES(3, 1, 'template', '', '', 'Easee Home', '{"charger":"EH123456","password":"none","template":"easee","timeout":"20s","user":"test@example.org"}'); INSERT INTO configs(id, class, type, title, icon, product, value) VALUES(3, 1, 'template', '', '', 'Alfen Eve', '{"host":"localhost","id":1,"modbus":"tcpip","port":502,"template":"alfen"}');
INSERT INTO configs(id, class, type, title, icon, product, value) VALUES(4, 5, '', '', '', '', '{"charger":"db:3","circuit":"","meter":"","phasesConfigured":0,"soc":{"poll":{"mode":"charging","interval":3600000000000},"estimate":true},"thresholds":{"enable":{"delay":60000000000,"threshold":0},"disable":{"delay":180000000000,"threshold":0}},"title":"Carport","vehicle":""}'); INSERT INTO configs(id, class, type, title, icon, product, value) VALUES(4, 5, '', '', '', '', '{"charger":"db:3","circuit":"","meter":"","phasesConfigured":0,"soc":{"poll":{"mode":"charging","interval":3600000000000},"estimate":true},"thresholds":{"enable":{"delay":60000000000,"threshold":0},"disable":{"delay":180000000000,"threshold":0}},"title":"Carport","vehicle":""}');
COMMIT; COMMIT;

View file

@ -19,6 +19,7 @@ package sponsor
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"os" "os"
"strings" "strings"
@ -28,6 +29,7 @@ import (
"github.com/evcc-io/evcc/api/proto/pb" "github.com/evcc-io/evcc/api/proto/pb"
"github.com/evcc-io/evcc/util/cloud" "github.com/evcc-io/evcc/util/cloud"
"github.com/evcc-io/evcc/util/machine" "github.com/evcc-io/evcc/util/machine"
"github.com/golang-jwt/jwt/v5"
"google.golang.org/grpc/codes" "google.golang.org/grpc/codes"
"google.golang.org/grpc/status" "google.golang.org/grpc/status"
) )
@ -111,6 +113,13 @@ func ConfigureSponsorship(token string) error {
Token = token Token = token
// check expiry locally to avoid cloud roundtrip
var claims jwt.RegisteredClaims
if _, _, err := jwt.NewParser().ParseUnverified(token, &claims); err == nil &&
claims.ExpiresAt != nil && claims.ExpiresAt.Before(time.Now()) {
return errors.New("token is expired - get a fresh one from https://sponsor.evcc.io")
}
conn, err := cloud.Connection() conn, err := cloud.Connection()
if err != nil { if err != nil {
return err return err