mirror of
https://github.com/home-assistant/core.git
synced 2025-08-15 16:30:04 +00:00
.devcontainer
.github
.vscode
homeassistant
machine
pylint
rootfs
script
tests
auth
components
fixtures
hassfest
helpers
snapshots
__init__.py
test_aiohttp_client.py
test_area_registry.py
test_check_config.py
test_collection.py
test_condition.py
test_config_entry_flow.py
test_config_entry_oauth2_flow.py
test_config_validation.py
test_debounce.py
test_deprecation.py
test_device_registry.py
test_discovery.py
test_discovery_flow.py
test_dispatcher.py
test_entity.py
test_entity_component.py
test_entity_platform.py
test_entity_registry.py
test_entity_values.py
test_entityfilter.py
test_event.py
test_floor_registry.py
test_frame.py
test_group.py
test_httpx_client.py
test_icon.py
test_init.py
test_instance_id.py
test_integration_platform.py
test_intent.py
test_issue_registry.py
test_json.py
test_label_registry.py
test_location.py
test_network.py
test_ratelimit.py
test_recorder.py
test_redact.py
test_reload.py
test_restore_state.py
test_schema_config_entry_flow.py
test_script.py
test_script_variables.py
test_selector.py
test_service.py
test_significant_change.py
test_singleton.py
test_start.py
test_state.py
test_storage.py
test_storage_remove.py
test_sun.py
test_system_info.py
test_temperature.py
test_template.py
test_translation.py
test_trigger.py
test_update_coordinator.py
pylint
resources
scripts
snapshots
test_util
testing_config
util
__init__.py
common.py
conftest.py
ignore_uncaught_exceptions.py
patch_time.py
ruff.toml
syrupy.py
test_bootstrap.py
test_config.py
test_config_entries.py
test_const.py
test_core.py
test_data_entry_flow.py
test_exceptions.py
test_loader.py
test_main.py
test_requirements.py
test_runner.py
test_setup.py
test_test_fixtures.py
typing.py
.core_files.yaml
.coveragerc
.dockerignore
.gitattributes
.gitignore
.hadolint.yaml
.pre-commit-config.yaml
.prettierignore
.strict-typing
.yamllint
CLA.md
CODEOWNERS
CODE_OF_CONDUCT.md
CONTRIBUTING.md
Dockerfile
Dockerfile.dev
LICENSE.md
MANIFEST.in
README.rst
build.yaml
codecov.yml
mypy.ini
pyproject.toml
requirements.txt
requirements_all.txt
requirements_test.txt
requirements_test_all.txt
requirements_test_pre_commit.txt
177 lines
5.6 KiB
Python
177 lines
5.6 KiB
Python
"""Test the frame helper."""
|
|
|
|
from collections.abc import Generator
|
|
from unittest.mock import ANY, Mock, patch
|
|
|
|
import pytest
|
|
|
|
from homeassistant.core import HomeAssistant
|
|
from homeassistant.helpers import frame
|
|
|
|
|
|
@pytest.fixture
|
|
def mock_integration_frame() -> Generator[Mock, None, None]:
|
|
"""Mock as if we're calling code from inside an integration."""
|
|
correct_frame = Mock(
|
|
filename="/home/paulus/homeassistant/components/hue/light.py",
|
|
lineno="23",
|
|
line="self.light.is_on",
|
|
)
|
|
with patch(
|
|
"homeassistant.helpers.frame.extract_stack",
|
|
return_value=[
|
|
Mock(
|
|
filename="/home/paulus/homeassistant/core.py",
|
|
lineno="23",
|
|
line="do_something()",
|
|
),
|
|
correct_frame,
|
|
Mock(
|
|
filename="/home/paulus/aiohue/lights.py",
|
|
lineno="2",
|
|
line="something()",
|
|
),
|
|
],
|
|
):
|
|
yield correct_frame
|
|
|
|
|
|
async def test_extract_frame_integration(
|
|
caplog: pytest.LogCaptureFixture, mock_integration_frame: Mock
|
|
) -> None:
|
|
"""Test extracting the current frame from integration context."""
|
|
integration_frame = frame.get_integration_frame()
|
|
assert integration_frame == frame.IntegrationFrame(
|
|
custom_integration=False,
|
|
frame=mock_integration_frame,
|
|
integration="hue",
|
|
module=None,
|
|
relative_filename="homeassistant/components/hue/light.py",
|
|
)
|
|
|
|
|
|
async def test_extract_frame_resolve_module(
|
|
hass: HomeAssistant, enable_custom_integrations
|
|
) -> None:
|
|
"""Test extracting the current frame from integration context."""
|
|
from custom_components.test_integration_frame import call_get_integration_frame
|
|
|
|
integration_frame = call_get_integration_frame()
|
|
|
|
assert integration_frame == frame.IntegrationFrame(
|
|
custom_integration=True,
|
|
frame=ANY,
|
|
integration="test_integration_frame",
|
|
module="custom_components.test_integration_frame",
|
|
relative_filename="custom_components/test_integration_frame/__init__.py",
|
|
)
|
|
|
|
|
|
async def test_extract_frame_integration_with_excluded_integration(
|
|
caplog: pytest.LogCaptureFixture,
|
|
) -> None:
|
|
"""Test extracting the current frame from integration context."""
|
|
correct_frame = Mock(
|
|
filename="/home/dev/homeassistant/components/mdns/light.py",
|
|
lineno="23",
|
|
line="self.light.is_on",
|
|
)
|
|
with patch(
|
|
"homeassistant.helpers.frame.extract_stack",
|
|
return_value=[
|
|
Mock(
|
|
filename="/home/dev/homeassistant/core.py",
|
|
lineno="23",
|
|
line="do_something()",
|
|
),
|
|
correct_frame,
|
|
Mock(
|
|
filename="/home/dev/homeassistant/components/zeroconf/usage.py",
|
|
lineno="23",
|
|
line="self.light.is_on",
|
|
),
|
|
Mock(
|
|
filename="/home/dev/mdns/lights.py",
|
|
lineno="2",
|
|
line="something()",
|
|
),
|
|
],
|
|
):
|
|
integration_frame = frame.get_integration_frame(
|
|
exclude_integrations={"zeroconf"}
|
|
)
|
|
|
|
assert integration_frame == frame.IntegrationFrame(
|
|
custom_integration=False,
|
|
frame=correct_frame,
|
|
integration="mdns",
|
|
module=None,
|
|
relative_filename="homeassistant/components/mdns/light.py",
|
|
)
|
|
|
|
|
|
async def test_extract_frame_no_integration(caplog: pytest.LogCaptureFixture) -> None:
|
|
"""Test extracting the current frame without integration context."""
|
|
with patch(
|
|
"homeassistant.helpers.frame.extract_stack",
|
|
return_value=[
|
|
Mock(
|
|
filename="/home/paulus/homeassistant/core.py",
|
|
lineno="23",
|
|
line="do_something()",
|
|
),
|
|
Mock(
|
|
filename="/home/paulus/aiohue/lights.py",
|
|
lineno="2",
|
|
line="something()",
|
|
),
|
|
],
|
|
), pytest.raises(frame.MissingIntegrationFrame):
|
|
frame.get_integration_frame()
|
|
|
|
|
|
@patch.object(frame, "_REPORTED_INTEGRATIONS", set())
|
|
async def test_prevent_flooding(
|
|
hass: HomeAssistant, caplog: pytest.LogCaptureFixture, mock_integration_frame: Mock
|
|
) -> None:
|
|
"""Test to ensure a report is only written once to the log."""
|
|
|
|
what = "accessed hi instead of hello"
|
|
key = "/home/paulus/homeassistant/components/hue/light.py:23"
|
|
integration = "hue"
|
|
filename = "homeassistant/components/hue/light.py"
|
|
|
|
expected_message = (
|
|
f"Detected that integration '{integration}' {what} at {filename}, line "
|
|
f"{mock_integration_frame.lineno}: {mock_integration_frame.line}, "
|
|
f"please create a bug report at https://github.com/home-assistant/core/issues?"
|
|
f"q=is%3Aopen+is%3Aissue+label%3A%22integration%3A+{integration}%22"
|
|
)
|
|
|
|
frame.report(what, error_if_core=False)
|
|
assert expected_message in caplog.text
|
|
assert key in frame._REPORTED_INTEGRATIONS
|
|
assert len(frame._REPORTED_INTEGRATIONS) == 1
|
|
|
|
caplog.clear()
|
|
|
|
frame.report(what, error_if_core=False)
|
|
assert expected_message not in caplog.text
|
|
assert key in frame._REPORTED_INTEGRATIONS
|
|
assert len(frame._REPORTED_INTEGRATIONS) == 1
|
|
|
|
|
|
async def test_report_missing_integration_frame(
|
|
caplog: pytest.LogCaptureFixture,
|
|
) -> None:
|
|
"""Test reporting when no integration is detected."""
|
|
|
|
what = "teststring"
|
|
with patch(
|
|
"homeassistant.helpers.frame.get_integration_frame",
|
|
side_effect=frame.MissingIntegrationFrame,
|
|
):
|
|
frame.report(what, error_if_core=False)
|
|
assert what in caplog.text
|
|
assert caplog.text.count(what) == 1
|