home-assistant / frontend

:lollipop: Frontend for Home Assistant
https://demo.home-assistant.io
Other
3.8k stars 2.6k forks source link

handleStructError cannot handle StructErrors of custom cards #21118

Open MichaelBrunn3r opened 2 weeks ago

MichaelBrunn3r commented 2 weeks ago

Checklist

Describe the issue you are experiencing

(I assume "Please do not report issues for custom cards" refers to issues regarding something like "Mushroom Cards". I hope this is the right place to report this)

Custom editor cards cannot display more than one error. HuiElementEditor._updateConfigElement calls setConfig on custom editor cards. If an error is thrown, it is passed to handleStructError. The function uses this code to handle errors that are not StructErrors (from superstruct):

if (!(err instanceof StructError)) {
   return { warnings: [err.message], errors: undefined };
}

Unfortunatelly, even when using superstruct for my own custom cards, the code thinks they are not StructErrors. My undertanding is, that instanceof checks if err.__proto__ and StructError are the same object. Since HomeAssistant and I both use our own instance of superstruct, our StructError classes are different objects.

Describe the behavior you expected

If a custom editors setConfig function returns a superstruct error, it should be displayed the same way HomeAssistant displays internal superstruct errors

Steps to reproduce the issue

import { object, string, assert } from "superstruct";

// Create a schema with superstruct
const CutomConfig = object({
    iamastring: string(),
});

// A custom card
class CustomCard {
    static getConfigElement() {
        return document.createElement("custom-card-editor");
     }
}
customElements.define("custom-card", CustomCard)

// Editor for CustomCard 
class CustomCardEditor {
    setConfig(config) {
        // validate the config with superstruct
        assert(config, CutomConfig);
    }
}
customElements.define("custom-card-editor", CustomCardEditor)

Set the config to an invalid value:

iamastring: 1 // number instead of string

What version of Home Assistant Core has the issue?

core-2024.6.2

What was the last working version of Home Assistant Core?

No response

In which browser are you experiencing the issue with?

No response

Which operating system are you using to run this browser?

No response

State of relevant entities

No response

Problem-relevant frontend configuration

No response

Javascript errors shown in your browser console/inspector

No response

Additional information

Superstruct error is treated like any other error: image

With some hacks the same error is displayed the same way HomeAssistant does it. It's even translated image

MichaelBrunn3r commented 2 weeks ago

Instead of fixing the issue with instanceof, I came up with an alternative solution.

if (!(err instanceof StructError)) {
    return { warnings: [err.message], errors: undefined };
}

The reason only one error from a superstruct error is displayed, is because we return an array with one element warnings: [err.message]. Instead we could check if the error has multiple messages:

if (!(err instanceof StructError)) {
    if(Array.isArray(err["messages"])) {
        return { warnings: err["messages"], errors: undefined };
    }
    return { warnings: [err.message], errors: undefined };
}

This way, custom cards creators could add a "messages" field to their errors, if they want to display multiple failures.