From abc66802ad36a23dea0162e1d5e3d433dfc91549 Mon Sep 17 00:00:00 2001 From: Michael Geers Date: Sat, 6 Jun 2026 17:22:52 +0200 Subject: [PATCH] chore: fix flaky sponsor and ext meter order tests (#30567) --- tests/config-ext-meter.spec.ts | 4 ++-- tests/issue.spec.ts | 2 +- tests/redact.evcc.yaml | 26 ++++++++++++++++++++++++++ tests/sponsor.evcc.yaml | 14 ++++++++------ tests/sponsor.sql | 2 +- util/sponsor/auth.go | 9 +++++++++ 6 files changed, 47 insertions(+), 10 deletions(-) create mode 100644 tests/redact.evcc.yaml diff --git a/tests/config-ext-meter.spec.ts b/tests/config-ext-meter.spec.ts index 698cd6051..d35b7b3ff 100644 --- a/tests/config-ext-meter.spec.ts +++ b/tests/config-ext-meter.spec.ts @@ -198,8 +198,8 @@ test.describe("ext meter order", async () => { // Restart and check order is preserved in both UIs await restart(CONFIG_BASICS); - // Check config UI - await page.goto("/#/config"); + // Check config UI, reload to reconnect websocket + await page.reload(); await expect(extMeters).toHaveCount(3); await expect(extMeters.nth(0)).toContainText("Meter 1"); await expect(extMeters.nth(1)).toContainText("Meter 2"); diff --git a/tests/issue.spec.ts b/tests/issue.spec.ts index 8f3fc99df..5b80d6527 100644 --- a/tests/issue.spec.ts +++ b/tests/issue.spec.ts @@ -17,7 +17,7 @@ test.afterEach(async () => { await stop(); }); -const REDACT_CONFIG = "sponsor.evcc.yaml"; +const REDACT_CONFIG = "redact.evcc.yaml"; const CONFIG = "issue.evcc.yaml"; test.describe("issue creation", () => { diff --git a/tests/redact.evcc.yaml b/tests/redact.evcc.yaml new file mode 100644 index 000000000..ea3f8d6e4 --- /dev/null +++ b/tests/redact.evcc.yaml @@ -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 diff --git a/tests/sponsor.evcc.yaml b/tests/sponsor.evcc.yaml index 25877d7d4..ffe070656 100644 --- a/tests/sponsor.evcc.yaml +++ b/tests/sponsor.evcc.yaml @@ -6,12 +6,14 @@ site: loadpoints: - title: Carport - charger: easee_charger + charger: alfen_charger chargers: - - name: easee_charger + # sponsorship-required charger without cloud communication + - name: alfen_charger type: template - template: easee - user: test@example.org - password: none - charger: EH123456 + template: alfen + modbus: tcpip + host: localhost + port: 502 + id: 1 diff --git a/tests/sponsor.sql b/tests/sponsor.sql index 47f6b4b8a..d7c98cd83 100644 --- a/tests/sponsor.sql +++ b/tests/sponsor.sql @@ -20,7 +20,7 @@ CREATE TABLE `configs` ( INSERT INTO settings("key", value) VALUES('sponsorToken', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJldmNjLmlvIiwic3ViIjoidHJpYWwiLCJleHAiOjE3NTQ5OTI4MDAsImlhdCI6MTc1MzY5NjgwMCwic3BlIjp0cnVlLCJzcmMiOiJtYSJ9.XKa5DHT-icCM9awcX4eS8feW0J_KIjsx2IxjcRRQOcQ'); -- 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":""}'); COMMIT; \ No newline at end of file diff --git a/util/sponsor/auth.go b/util/sponsor/auth.go index 0991a5bcf..1bcf3d03f 100644 --- a/util/sponsor/auth.go +++ b/util/sponsor/auth.go @@ -19,6 +19,7 @@ package sponsor import ( "context" + "errors" "fmt" "os" "strings" @@ -28,6 +29,7 @@ import ( "github.com/evcc-io/evcc/api/proto/pb" "github.com/evcc-io/evcc/util/cloud" "github.com/evcc-io/evcc/util/machine" + "github.com/golang-jwt/jwt/v5" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) @@ -111,6 +113,13 @@ func ConfigureSponsorship(token string) error { 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() if err != nil { return err