1
0
mirror of https://github.com/home-assistant/core.git synced 2026-05-08 17:49:37 +01:00

Add support for multiple entries to Xbox integration (#155771)

This commit is contained in:
Manu
2025-11-04 09:00:40 +01:00
committed by GitHub
parent 0e2a4605ff
commit ff364e3913
5 changed files with 76 additions and 21 deletions
+1 -4
View File
@@ -38,10 +38,6 @@ class OAuth2FlowHandler(
self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult:
"""Handle a flow start."""
if self._async_current_entries():
return self.async_abort(reason="single_instance_allowed")
return await super().async_step_user(user_input)
async def async_oauth_create_entry(self, data: dict) -> ConfigFlowResult:
@@ -57,4 +53,5 @@ class OAuth2FlowHandler(
me = await client.people.get_friends_by_xuid(client.xuid)
await self.async_set_unique_id(client.xuid)
self._abort_if_unique_id_configured()
return self.async_create_entry(title=me.people[0].gamertag, data=data)
+20 -4
View File
@@ -199,8 +199,13 @@ class XboxUpdateCoordinator(DataUpdateCoordinator[XboxData]):
) from e
else:
presence_data = {self.client.xuid: batch.people[0]}
configured_xuids = self.configured_as_entry()
presence_data.update(
{friend.xuid: friend for friend in friends.people if friend.is_favorite}
{
friend.xuid: friend
for friend in friends.people
if friend.is_favorite and friend.xuid not in configured_xuids
}
)
# retrieve title details
@@ -252,9 +257,11 @@ class XboxUpdateCoordinator(DataUpdateCoordinator[XboxData]):
"""Remove stale devices from registry."""
device_reg = dr.async_get(self.hass)
identifiers = {(DOMAIN, xuid) for xuid in xuids} | {
(DOMAIN, console.id) for console in self.consoles.result
}
identifiers = (
{(DOMAIN, xuid) for xuid in xuids}
| {(DOMAIN, console.id) for console in self.consoles.result}
| self.configured_as_entry()
)
for device in dr.async_entries_for_config_entry(
device_reg, self.config_entry.entry_id
@@ -264,3 +271,12 @@ class XboxUpdateCoordinator(DataUpdateCoordinator[XboxData]):
device_reg.async_update_device(
device.id, remove_config_entry_id=self.config_entry.entry_id
)
def configured_as_entry(self) -> set[str]:
"""Get xuids of configured entries."""
return {
entry.unique_id
for entry in self.hass.config_entries.async_entries(DOMAIN)
if entry.unique_id is not None
}
+2 -2
View File
@@ -1,13 +1,13 @@
{
"config": {
"abort": {
"already_configured": "[%key:common::config_flow::abort::already_configured_account%]",
"authorize_url_timeout": "[%key:common::config_flow::abort::oauth2_authorize_url_timeout%]",
"missing_configuration": "[%key:common::config_flow::abort::oauth2_missing_configuration%]",
"oauth_error": "[%key:common::config_flow::abort::oauth2_error%]",
"oauth_failed": "[%key:common::config_flow::abort::oauth2_failed%]",
"oauth_timeout": "[%key:common::config_flow::abort::oauth2_timeout%]",
"oauth_unauthorized": "[%key:common::config_flow::abort::oauth2_unauthorized%]",
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]"
"oauth_unauthorized": "[%key:common::config_flow::abort::oauth2_unauthorized%]"
},
"create_entry": {
"default": "[%key:common::config_flow::create_entry::authenticated%]"
+1
View File
@@ -67,6 +67,7 @@ def mock_config_entry() -> MockConfigEntry:
"user_id": "AAAAAAAAAAAAAAAAAAAAA",
},
},
unique_id="271958441785640",
)
+52 -11
View File
@@ -18,17 +18,6 @@ from tests.test_util.aiohttp import AiohttpClientMocker
from tests.typing import ClientSessionGenerator
async def test_abort_if_existing_entry(hass: HomeAssistant) -> None:
"""Check flow abort when an entry already exist."""
MockConfigEntry(domain=DOMAIN).add_to_hass(hass)
result = await hass.config_entries.flow.async_init(
"xbox", context={"source": config_entries.SOURCE_USER}
)
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "single_instance_allowed"
@pytest.mark.usefixtures(
"current_request_with_host",
"xbox_live_client",
@@ -90,6 +79,58 @@ async def test_full_flow(
assert len(mock_setup.mock_calls) == 1
@pytest.mark.usefixtures(
"current_request_with_host",
"xbox_live_client",
"authentication_manager",
)
async def test_form_already_configured(
hass: HomeAssistant,
hass_client_no_auth: ClientSessionGenerator,
aioclient_mock: AiohttpClientMocker,
config_entry: MockConfigEntry,
) -> None:
"""Test we abort flow when entry is already configured."""
config_entry.add_to_hass(hass)
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER}
)
state = config_entry_oauth2_flow._encode_jwt(
hass,
{
"flow_id": result["flow_id"],
"redirect_uri": "https://example.com/auth/external/callback",
},
)
client = await hass_client_no_auth()
resp = await client.get(f"/auth/external/callback?code=abcd&state={state}")
assert resp.status == HTTPStatus.OK
assert resp.headers["content-type"] == "text/html; charset=utf-8"
aioclient_mock.post(
OAUTH2_TOKEN,
json={
"refresh_token": "mock-refresh-token",
"access_token": "mock-access-token",
"type": "Bearer",
"expires_in": 60,
"scope": "XboxLive.signin XboxLive.offline_access",
"service": "xbox",
"token_type": "bearer",
"user_id": "AAAAAAAAAAAAAAAAAAAAA",
},
)
result = await hass.config_entries.flow.async_configure(result["flow_id"])
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "already_configured"
@pytest.mark.usefixtures("xbox_live_client")
async def test_unique_id_migration(
hass: HomeAssistant,