Esempio n. 1
0
def test_conversion_not_attempted_if_target_currency_same(hass):
    """No conversion is attempted if target curency is the same as symbol currency."""

    symbol = "XYZ"
    mock_coordinator = build_mock_coordinator(hass, True, symbol, 12)

    # Force update _previous_close to None
    mock_coordinator.data[symbol][DATA_REGULAR_MARKET_PREVIOUS_CLOSE] = None

    sensor = YahooFinanceSensor(
        hass,
        mock_coordinator,
        {
            "symbol": symbol,
            CONF_TARGET_CURRENCY: "USD"
        },
        DEFAULT_OPTIONAL_CONFIG,
    )

    with patch.object(mock_coordinator, "add_symbol") as mock_add_symbol:
        # Accessing `available` triggers data population
        assert sensor.available is True

        # The mock data has currency USD and target is USD too.
        assert mock_add_symbol.call_count == 0
Esempio n. 2
0
def test_sensor_trending_state_is_not_populate_if_previous_closing_missing(
        hass):
    """The trending state is None if _previous_close is None for some reason."""

    symbol = "XYZ"
    mock_coordinator = build_mock_coordinator(hass, True, symbol, 12)

    # Force update _previous_close to None
    mock_coordinator.data[symbol][DATA_REGULAR_MARKET_PREVIOUS_CLOSE] = None

    config = copy.deepcopy(DEFAULT_OPTIONAL_CONFIG)
    config[CONF_SHOW_TRENDING_ICON] = True

    sensor = YahooFinanceSensor(hass, mock_coordinator, {"symbol": symbol},
                                config)

    # Accessing `available` triggers data population
    assert sensor.available is True

    # ATTR_TRENDING should always reflect the trending status regarding of CONF_SHOW_TRENDING_ICON
    assert (ATTR_TRENDING in sensor.device_state_attributes) is False

    # icon is based on the currency
    currency = sensor.unit_of_measurement
    lower_currency = currency.lower()
    assert sensor.icon == f"mdi:currency-{lower_currency}"
Esempio n. 3
0
def test_sensor_creation(hass, last_update_success, symbol, market_price,
                         expected_market_price):
    """Test sensor status based on the expected_market_price."""

    mock_coordinator = build_mock_coordinator(hass, last_update_success,
                                              symbol, market_price)

    sensor = YahooFinanceSensor(hass, mock_coordinator, {"symbol": symbol},
                                DEFAULT_OPTIONAL_CONFIG)

    # Accessing `available` triggers data population
    assert sensor.available is last_update_success

    # state represents the rounded market price
    assert sensor.state == expected_market_price
    assert sensor.name == f"Symbol {symbol}"

    attributes = sensor.device_state_attributes
    # Sensor would be trending up because _previous_close is 0.
    assert attributes[ATTR_TRENDING] == "up"

    # All numeric values besides DATA_REGULAR_MARKET_PRICE should be 0
    for numeric_data_key in NUMERIC_DATA_GROUPS:
        for value in NUMERIC_DATA_GROUPS[numeric_data_key]:
            key = value[0]
            if key != DATA_REGULAR_MARKET_PRICE:
                assert attributes[key] == 0

    # Since we did not provide any data so currency should be the default value
    assert sensor.unit_of_measurement == DEFAULT_CURRENCY
    assert attributes[ATTR_CURRENCY_SYMBOL] == DEFAULT_CURRENCY_SYMBOL

    assert sensor.should_poll is False
Esempio n. 4
0
def test_sensor_trend(hass, market_price, previous_close, show_trending,
                      expected_trend):
    """Test sensor trending status."""

    symbol = "XYZ"
    mock_coordinator = build_mock_coordinator(hass, True, symbol, market_price)
    mock_coordinator.data[symbol][
        DATA_REGULAR_MARKET_PREVIOUS_CLOSE] = previous_close

    config = copy.deepcopy(DEFAULT_OPTIONAL_CONFIG)
    config[CONF_SHOW_TRENDING_ICON] = show_trending

    sensor = YahooFinanceSensor(hass, mock_coordinator, {"symbol": symbol},
                                config)

    # Accessing `available` triggers data population
    assert sensor.available is True

    # ATTR_TRENDING should always reflect the trending status regarding of CONF_SHOW_TRENDING_ICON
    assert sensor.device_state_attributes[ATTR_TRENDING] == expected_trend

    if show_trending:
        assert sensor.icon == f"mdi:trending-{expected_trend}"
    else:
        currency = sensor.unit_of_measurement
        lower_currency = currency.lower()
        assert sensor.icon == f"mdi:currency-{lower_currency}"
Esempio n. 5
0
async def test_setup_listener_unregistration(hass):
    """Test entity listener unregistration."""
    symbol = "XYZ"
    mock_coordinator = build_mock_coordinator(hass, True, symbol, 12)

    sensor = YahooFinanceSensor(hass, mock_coordinator, {"symbol": symbol},
                                DEFAULT_OPTIONAL_CONFIG)

    await sensor.async_will_remove_from_hass()
    assert mock_coordinator.async_remove_listener.call_count == 1
Esempio n. 6
0
async def test_sensor_update_calls_coordinator(hass):
    """Test sensor data update."""

    symbol = "XYZ"
    mock_coordinator = build_mock_coordinator(hass, True, symbol, None)
    mock_coordinator.async_request_refresh = AsyncMock(return_value=None)
    sensor = YahooFinanceSensor(hass, mock_coordinator, {"symbol": symbol},
                                DEFAULT_OPTIONAL_CONFIG)

    await sensor.async_update()
    assert mock_coordinator.async_request_refresh.call_count == 1
Esempio n. 7
0
def test_sensor_decimal_placs(hass, market_price, decimal_places,
                              expected_market_price):
    """Tests numeric value rounding."""

    symbol = "XYZ"
    mock_coordinator = build_mock_coordinator(hass, True, symbol, market_price)

    config = copy.deepcopy(SAMPLE_VALID_CONFIG)
    config[CONF_DECIMAL_PLACES] = decimal_places

    sensor = YahooFinanceSensor(hass, mock_coordinator, symbol, config)

    # Accessing `available` triggers data population
    assert sensor.available is True

    # state represents the rounded market price
    assert sensor.state == expected_market_price
Esempio n. 8
0
def test_repeated_available(hass):
    """Test repeated calls to available."""

    symbol = "XYZ"
    market_price = 12
    symbol_data = build_mock_symbol_data(symbol, market_price)
    # symbol_data[DATA_REGULAR_MARKET_PREVIOUS_CLOSE] = market_price

    mock_coordinator = Mock()
    mock_data = PropertyMock(return_value=symbol_data)
    type(mock_coordinator).data = mock_data

    sensor = YahooFinanceSensor(hass, mock_coordinator, {"symbol": symbol},
                                DEFAULT_OPTIONAL_CONFIG)

    # Calling available in quick successions results in property updates once
    assert sensor.available
    assert sensor.available
    assert mock_data.call_count == 1
Esempio n. 9
0
def test_sensor_data_when_coordinator_returns_none(hass):
    """Test sensor status when data coordinator does not have any data."""

    symbol = "XYZ"
    mock_coordinator = Mock(
        data=None,
        hass=hass,
        last_update_success=False,
    )

    sensor = YahooFinanceSensor(hass, mock_coordinator, {"symbol": symbol},
                                DEFAULT_OPTIONAL_CONFIG)

    # Accessing `available` triggers data population
    assert sensor.available is False

    assert sensor.state is None
    # Since we do not have data so the name will be the symbol
    assert sensor.name == symbol
Esempio n. 10
0
def test_sensor_data_when_coordinator_is_missing_symbol_data(
        hass, last_update_success, symbol, market_price):
    """Test sensor status when data coordinator does not have data for that symbol."""

    mock_coordinator = build_mock_coordinator(hass, last_update_success,
                                              symbol, market_price)

    # Create a sensor for some other symbol
    symbol_to_test = "ABC"
    sensor = YahooFinanceSensor(hass, mock_coordinator, symbol_to_test,
                                SAMPLE_VALID_CONFIG)

    # Accessing `available` triggers data population
    assert sensor.available is last_update_success

    assert sensor.state is None

    # Symbol is used as name when there is no data
    assert sensor.name == symbol_to_test
Esempio n. 11
0
async def test_data_from_json(hass, mock_json):
    """Tests data update all the way from from json."""
    symbol = "BABA"
    coordinator = YahooSymbolUpdateCoordinator([symbol], hass,
                                               DEFAULT_SCAN_INTERVAL)
    coordinator.get_json = AsyncMock(return_value=mock_json)

    await coordinator.async_refresh()
    await hass.async_block_till_done()

    sensor = YahooFinanceSensor(hass, coordinator, symbol, SAMPLE_VALID_CONFIG)

    # Accessing `available` triggers data population
    assert sensor.available is True

    attributes = sensor.device_state_attributes

    assert sensor.state == 232.73
    assert attributes["regularMarketChange"] == -5.66
    assert attributes["twoHundredDayAverageChangePercent"] == -0.13
Esempio n. 12
0
def test_conversion_requests_additional_data_from_coordinator(hass):
    """Numeric values get multiplied based on conversion currency."""

    symbol = "XYZ"
    mock_coordinator = build_mock_coordinator(hass, True, symbol, 12)

    # Force update _previous_close to None
    mock_coordinator.data[symbol][DATA_REGULAR_MARKET_PREVIOUS_CLOSE] = None

    sensor = YahooFinanceSensor(
        hass,
        mock_coordinator,
        {"symbol": symbol, CONF_TARGET_CURRENCY: "EUR"},
        SAMPLE_VALID_CONFIG,
    )

    with patch.object(mock_coordinator, "add_symbol") as mock_add_symbol:
        # Accessing `available` triggers data population
        assert sensor.available is True

        assert mock_add_symbol.call_count == 1
Esempio n. 13
0
def test_conversion(hass):
    """Numeric values get multiplied based on conversion currency."""

    symbol = "XYZ"
    mock_coordinator = build_mock_coordinator_for_conversion(
        hass, symbol, 12, "USD", "CHF", 1.5
    )

    # Force update _previous_close to None
    mock_coordinator.data[symbol][DATA_REGULAR_MARKET_PREVIOUS_CLOSE] = None

    sensor = YahooFinanceSensor(
        hass,
        mock_coordinator,
        {"symbol": symbol, CONF_TARGET_CURRENCY: "CHF"},
        SAMPLE_VALID_CONFIG,
    )

    # Accessing `available` triggers data population
    assert sensor.available is True
    assert sensor.state == (12 * 1.5)
Esempio n. 14
0
def test_safe_convert(value, conversion, expected):
    """Test value conversion."""
    assert YahooFinanceSensor.safe_convert(value, conversion) == expected