Repository: home-assistant/core
File: tests/components/saunum/test_config_flow.py (Python)

Code before:

    assert result["type"] is FlowResultType.CREATE_ENTRY
    assert result["title"] == "Saunum"
    assert result["data"] == TEST_USER_INPUT


@pytest.mark.parametrize(
    ("side_effect", "error_base"),
    [
        (SaunumConnectionError("Connection failed"), "cannot_connect"),
        (SaunumException("Read error"), "cannot_connect"),
        (Exception("Unexpected error"), "unknown"),
    ],
)
async def test_form_errors(
    hass: HomeAssistant,
    mock_saunum_client,
    side_effect: Exception,
    error_base: str,
    mock_setup_entry: AsyncMock,
) -> None:
    """Test error handling and recovery."""
    with patch(
        "homeassistant.components.saunum.config_flow.SaunumClient.create",
        side_effect=side_effect,
    ):
        result = await hass.config_entries.flow.async_init(
            DOMAIN, context={"source": SOURCE_USER}
        )

        result = await hass.config_entries.flow.async_configure(
            result["flow_id"],
            TEST_USER_INPUT,
        )

        assert result["type"] is FlowResultType.FORM
        assert result["errors"] == {"base": error_base}

    # Test recovery - try again without the error

    result = await hass.config_entries.flow.async_configure(
        result["flow_id"],
        TEST_USER_INPUT,
    )

    assert result["type"] is FlowResultType.CREATE_ENTRY
    assert result["title"] == "Saunum"
    assert result["data"] == TEST_USER_INPUT


@pytest.mark.usefixtures("mock_saunum_client")

Review comment (suggestion):
You likely want to change the `mock_saunum_client` to not return the `client.return_value` but just the `client`.

I'd recommend:
1. rename `mock_saunum_client` and make it just return the raw mock (the one assigned in `with patch(...) as client`)
2. Create a new fixture that imports `mock_saunum_client` (the renamed one) and returns `mock_saunum_client.return_value`. This new fixture would then be called `mock_saunum_client`.

This would keep your tests intact and allows to keep using the existing mock and avoid inline patches

Code after:

    assert result["type"] is FlowResultType.CREATE_ENTRY
    assert result["title"] == "Saunum"
    assert result["data"] == TEST_USER_INPUT


@pytest.mark.parametrize(
    ("side_effect", "error_base"),
    [
        (SaunumConnectionError("Connection failed"), "cannot_connect"),
        (SaunumException("Read error"), "cannot_connect"),
        (Exception("Unexpected error"), "unknown"),
    ],
)
async def test_form_errors(
    hass: HomeAssistant,
    mock_saunum_client_class,
    side_effect: Exception,
    error_base: str,
    mock_setup_entry: AsyncMock,
) -> None:
    """Test error handling and recovery."""
    mock_saunum_client_class.create.side_effect = side_effect
    result = await hass.config_entries.flow.async_init(
        DOMAIN, context={"source": SOURCE_USER}
    )

    result = await hass.config_entries.flow.async_configure(
        result["flow_id"],
        TEST_USER_INPUT,
    )

    assert result["type"] is FlowResultType.FORM
    assert result["errors"] == {"base": error_base}

    # Test recovery - try again without the error
    mock_saunum_client_class.create.side_effect = None

    result = await hass.config_entries.flow.async_configure(
        result["flow_id"],
        TEST_USER_INPUT,
    )

    assert result["type"] is FlowResultType.CREATE_ENTRY
    assert result["title"] == "Saunum"
    assert result["data"] == TEST_USER_INPUT


@pytest.mark.usefixtures("mock_saunum_client")
async def test_form_duplicate(
    hass: HomeAssistant, mock_config_entry: MockConfigEntry