Add config flow to discord (#61069)
This commit is contained in:
60
tests/components/discord/__init__.py
Normal file
60
tests/components/discord/__init__.py
Normal file
@@ -0,0 +1,60 @@
|
||||
"""Tests for the Discord integration."""
|
||||
|
||||
from unittest.mock import AsyncMock, Mock, patch
|
||||
|
||||
import nextcord
|
||||
|
||||
from homeassistant.components.discord.const import DOMAIN
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_API_TOKEN, CONF_NAME, CONF_TOKEN
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
TOKEN = "abc123"
|
||||
NAME = "Discord Bot"
|
||||
|
||||
CONF_INPUT = {CONF_API_TOKEN: TOKEN}
|
||||
|
||||
CONF_DATA = {
|
||||
CONF_API_TOKEN: TOKEN,
|
||||
CONF_NAME: NAME,
|
||||
}
|
||||
|
||||
CONF_IMPORT_DATA_NO_NAME = {CONF_TOKEN: TOKEN}
|
||||
|
||||
CONF_IMPORT_DATA = CONF_IMPORT_DATA_NO_NAME | {CONF_NAME: NAME}
|
||||
|
||||
|
||||
def create_entry(hass: HomeAssistant) -> ConfigEntry:
|
||||
"""Add config entry in Home Assistant."""
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
data=CONF_DATA,
|
||||
unique_id="1234567890",
|
||||
)
|
||||
entry.add_to_hass(hass)
|
||||
return entry
|
||||
|
||||
|
||||
def mocked_discord_info():
|
||||
"""Create mocked discord."""
|
||||
mocked_discord = AsyncMock()
|
||||
mocked_discord.id = "1234567890"
|
||||
mocked_discord.name = NAME
|
||||
return patch(
|
||||
"homeassistant.components.discord.config_flow.nextcord.Client.application_info",
|
||||
return_value=mocked_discord,
|
||||
)
|
||||
|
||||
|
||||
def patch_discord_login():
|
||||
"""Patch discord info."""
|
||||
return patch("homeassistant.components.discord.config_flow.nextcord.Client.login")
|
||||
|
||||
|
||||
def mock_exception():
|
||||
"""Mock response."""
|
||||
response = Mock()
|
||||
response.status = 404
|
||||
return nextcord.HTTPException(response, "")
|
||||
206
tests/components/discord/test_config_flow.py
Normal file
206
tests/components/discord/test_config_flow.py
Normal file
@@ -0,0 +1,206 @@
|
||||
"""Test Discord config flow."""
|
||||
import nextcord
|
||||
from pytest import LogCaptureFixture
|
||||
|
||||
from homeassistant import config_entries, data_entry_flow
|
||||
from homeassistant.components.discord.const import DOMAIN
|
||||
from homeassistant.const import CONF_API_TOKEN, CONF_SOURCE
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from . import (
|
||||
CONF_DATA,
|
||||
CONF_IMPORT_DATA,
|
||||
CONF_IMPORT_DATA_NO_NAME,
|
||||
CONF_INPUT,
|
||||
NAME,
|
||||
create_entry,
|
||||
mock_exception,
|
||||
mocked_discord_info,
|
||||
patch_discord_login,
|
||||
)
|
||||
|
||||
|
||||
async def test_flow_user(hass: HomeAssistant) -> None:
|
||||
"""Test user initialized flow."""
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": config_entries.SOURCE_USER},
|
||||
)
|
||||
with mocked_discord_info(), patch_discord_login():
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
user_input=CONF_INPUT,
|
||||
)
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
|
||||
assert result["title"] == NAME
|
||||
assert result["data"] == CONF_DATA
|
||||
|
||||
|
||||
async def test_flow_user_already_configured(hass: HomeAssistant) -> None:
|
||||
"""Test user initialized flow with duplicate server."""
|
||||
create_entry(hass)
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": config_entries.SOURCE_USER},
|
||||
)
|
||||
with mocked_discord_info(), patch_discord_login():
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
user_input=CONF_INPUT,
|
||||
)
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
|
||||
assert result["reason"] == "already_configured"
|
||||
|
||||
|
||||
async def test_flow_user_invalid_auth(hass: HomeAssistant) -> None:
|
||||
"""Test user initialized flow with invalid token."""
|
||||
with patch_discord_login() as mock:
|
||||
mock.side_effect = nextcord.LoginFailure
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": config_entries.SOURCE_USER},
|
||||
data=CONF_DATA,
|
||||
)
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||
assert result["step_id"] == "user"
|
||||
assert result["errors"] == {"base": "invalid_auth"}
|
||||
|
||||
with mocked_discord_info(), patch_discord_login():
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
user_input=CONF_INPUT,
|
||||
)
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
|
||||
assert result["title"] == NAME
|
||||
assert result["data"] == CONF_DATA
|
||||
|
||||
|
||||
async def test_flow_user_cannot_connect(hass: HomeAssistant) -> None:
|
||||
"""Test user initialized flow with unreachable server."""
|
||||
with patch_discord_login() as mock:
|
||||
mock.side_effect = mock_exception()
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": config_entries.SOURCE_USER},
|
||||
data=CONF_DATA,
|
||||
)
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||
assert result["step_id"] == "user"
|
||||
assert result["errors"] == {"base": "cannot_connect"}
|
||||
|
||||
with mocked_discord_info(), patch_discord_login():
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
user_input=CONF_INPUT,
|
||||
)
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
|
||||
assert result["title"] == NAME
|
||||
assert result["data"] == CONF_DATA
|
||||
|
||||
|
||||
async def test_flow_user_unknown_error(hass: HomeAssistant) -> None:
|
||||
"""Test user initialized flow with unreachable server."""
|
||||
with patch_discord_login() as mock:
|
||||
mock.side_effect = Exception
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": config_entries.SOURCE_USER},
|
||||
data=CONF_DATA,
|
||||
)
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||
assert result["step_id"] == "user"
|
||||
assert result["errors"] == {"base": "unknown"}
|
||||
|
||||
with mocked_discord_info(), patch_discord_login():
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
user_input=CONF_INPUT,
|
||||
)
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
|
||||
assert result["title"] == NAME
|
||||
assert result["data"] == CONF_DATA
|
||||
|
||||
|
||||
async def test_flow_import(hass: HomeAssistant, caplog: LogCaptureFixture) -> None:
|
||||
"""Test an import flow."""
|
||||
with mocked_discord_info(), patch_discord_login():
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": config_entries.SOURCE_IMPORT},
|
||||
data=CONF_IMPORT_DATA.copy(),
|
||||
)
|
||||
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
|
||||
assert result["title"] == NAME
|
||||
assert result["data"] == CONF_DATA
|
||||
assert "Discord integration in YAML" in caplog.text
|
||||
|
||||
|
||||
async def test_flow_import_no_name(hass: HomeAssistant) -> None:
|
||||
"""Test import flow with no name in config."""
|
||||
with mocked_discord_info(), patch_discord_login():
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": config_entries.SOURCE_IMPORT},
|
||||
data=CONF_IMPORT_DATA_NO_NAME,
|
||||
)
|
||||
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
|
||||
assert result["title"] == NAME
|
||||
assert result["data"] == CONF_DATA
|
||||
|
||||
|
||||
async def test_flow_import_already_configured(hass: HomeAssistant) -> None:
|
||||
"""Test an import flow already configured."""
|
||||
create_entry(hass)
|
||||
with mocked_discord_info(), patch_discord_login():
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": config_entries.SOURCE_IMPORT},
|
||||
data=CONF_IMPORT_DATA,
|
||||
)
|
||||
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
|
||||
assert result["reason"] == "already_configured"
|
||||
|
||||
|
||||
async def test_flow_reauth(hass: HomeAssistant) -> None:
|
||||
"""Test a reauth flow."""
|
||||
entry = create_entry(hass)
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={
|
||||
CONF_SOURCE: config_entries.SOURCE_REAUTH,
|
||||
"entry_id": entry.entry_id,
|
||||
"unique_id": entry.unique_id,
|
||||
},
|
||||
)
|
||||
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||
assert result["step_id"] == "reauth"
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
user_input={},
|
||||
)
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||
assert result["step_id"] == "reauth_confirm"
|
||||
|
||||
new_conf = {CONF_API_TOKEN: "1234567890123"}
|
||||
with patch_discord_login() as mock:
|
||||
mock.side_effect = nextcord.LoginFailure
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
user_input=new_conf,
|
||||
)
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||
assert result["step_id"] == "reauth_confirm"
|
||||
assert result["errors"] == {"base": "invalid_auth"}
|
||||
|
||||
with mocked_discord_info(), patch_discord_login():
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
user_input=new_conf,
|
||||
)
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
|
||||
assert result["reason"] == "reauth_successful"
|
||||
assert entry.data == CONF_DATA | new_conf
|
||||
Reference in New Issue
Block a user