-
-
Notifications
You must be signed in to change notification settings - Fork 36.5k
Handle router initialization, connection errors, and missing interfaces in options flow #143475
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Handle router initialization, connection errors, and missing interfaces in options flow #143475
Conversation
| try: | ||
| router: KeeneticRouter = self.hass.data[DOMAIN][self.config_entry.entry_id][ | ||
| ROUTER | ||
| ] | ||
| except KeyError: | ||
| return self.async_abort(reason="not_initialized") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead let's check if the value we want to use is there instead of letting it raise a KeyError
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@joostlek , thanks for the review. done
| entry = MockConfigEntry(domain=keenetic.DOMAIN, data=MOCK_DATA) | ||
| entry.add_to_hass(hass) | ||
|
|
||
| # no router set | ||
| hass.data.setdefault(keenetic.DOMAIN, {}) | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| entry = MockConfigEntry(domain=keenetic.DOMAIN, data=MOCK_DATA) | |
| entry.add_to_hass(hass) | |
| # no router set | |
| hass.data.setdefault(keenetic.DOMAIN, {}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi. I don't understand this suggestion. Is it to remove an empty line? I think it's good there to separate the preparation and the 'result = ...' line
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay let me rephrase, we should not touch internals like hass.data and I think you can create the mock config entry as something we can reuse
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should mock the library and have HA set up the integration like normal
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This part is not touching any internals. hass.data is the state collection where any integration is free to store its state under their domain. And we just put a desired test state there (no state in this particular test).
The test verifies the config flow in case the integration initialization is not complete for any reason. Since this test does not check the integration entirely and only the configuration, we are not trying to make the integration fail. Instead, we mock the integration part in a state which is the testing condition for the config flow.
So this is perfectly normal.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This part is not touching any internals. hass.data is the state collection where any integration is free to store its state under their domain.
No, hass.data is considered internal. We can set that to anything we like and then we have the assumption that HA sets it like that. Those lead to fragile tests and thus we consider hass.data as internal. Many integrations are moving to storing their runtime data in entry.runtime_data and that migration ideally should happen without changes in the tests as the tests should not care where the data comes from
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK. This is something new AFAIK.
However, since this PR does not perform a migration, the tests match how the integration and options flow work. I can do the migration to entry.runtime_data later along with the strict typing changes I have in my stash. Then there will be no touching of hass.data.
We can set that to anything we like and then we have the assumption that HA sets it like that.
You mean "writing a test we have the assumption that HA sets it like that"?. But that's not exactly true. Writing a test for the flow we know: a. the flow will be reading this, b. the integration is expected to be setting this if it's loaded.
In summary, this is a unit test for the flow, and it's specifically testing the case where the integration is not yet loaded. So anyway, no need to initialize the integration entity in the test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @joostlek
So somebody migrated the integration to runtime_data for me. No touching of hass anymore. Please review
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fun fact, entry.runtime_data is still considered internal. I merged that PR as that didn't change it, but I think we should refactor the tests to make sure we only take control of the library and then just have HA do its think and observe via the state machine.
But let's merge this for now and I would appreciate if we can refactor the tests.
|
Please take a look at the requested changes, and use the Ready for review button when you are done, thanks 👍 |
86ae6d3 to
cb442c6
Compare
|
Hi, @joostlek . Can you please take another look at the PR? |
|
It's not marked as ready for review yet |
|
@joostlek I was sure it is. Set ready |
| entry = MockConfigEntry(domain=keenetic.DOMAIN, data=MOCK_DATA) | ||
| entry.add_to_hass(hass) | ||
|
|
||
| # no router set | ||
| hass.data.setdefault(keenetic.DOMAIN, {}) | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay let me rephrase, we should not touch internals like hass.data and I think you can create the mock config entry as something we can reuse
| entry = MockConfigEntry(domain=keenetic.DOMAIN, data=MOCK_DATA) | ||
| entry.add_to_hass(hass) | ||
|
|
||
| # no router set | ||
| hass.data.setdefault(keenetic.DOMAIN, {}) | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should mock the library and have HA set up the integration like normal
Added checks in the Keenetic NDMS2 options flow to handle cases where the integration is not initialized or there are connection errors. Relevant user feedback and abort reasons are now provided to ensure a better user experience.
7922c69 to
040f57c
Compare
…es in options flow (home-assistant#143475) * Handle router initialization and connection errors in options flow Added checks in the Keenetic NDMS2 options flow to handle cases where the integration is not initialized or there are connection errors. Relevant user feedback and abort reasons are now provided to ensure a better user experience. * Add filtering saved/default options for interfaces before preparing an options form
Breaking change
Proposed change
Added checks in the Keenetic NDMS2 options flow to handle cases where the integration is not initialized or there are connection errors. Relevant user feedback and abort reasons are now provided to ensure a better user experience.
Also added filtering out unavailable options for the config flow, since the frontent does not do that
Type of change
Additional information
Checklist
ruff format homeassistant tests)If user exposed functionality or configuration variables are added/changed:
If the code communicates with devices, web services, or third-party tools:
Updated and included derived files by running:
python3 -m script.hassfest.requirements_all.txt.Updated by running
python3 -m script.gen_requirements_all.To help with the load of incoming pull requests: