"""Features tests.""" import flask from flask import g from owsrequest import request from owsrequest import test_utils from owsresponse import response from pytest import raises from owsfeatures import features from owsfeatures.constant import header from owsfeatures.features import FEATURES_ATTRIBUTE from owsfeatures.features import UNINITIALIZED_ERROR from owsfeatures.models import ows_features def test_check_feature_without_fetching_raises_exception(testapp): """Checking a feature without loading first won't work.""" with testapp.test_request_context(): with raises(Exception) as exception_info: features.is_feature_enabled('awesome_feature') assert UNINITIALIZED_ERROR in str(exception_info.value) def test_check_feature_with_features_fetched_but_missing_is_false( testapp): """Checking a feature that isn't present is false.""" with testapp.test_request_context(): setattr(g, FEATURES_ATTRIBUTE, {}) result = features.is_feature_enabled('awesome_feature') assert result is False def test_check_feature_set_to_enabled_is_true(testapp): """Checking a present and enabled feature is true.""" with testapp.test_request_context(): setattr(g, FEATURES_ATTRIBUTE, {'awesome_feature': 'enabled'}) result = features.is_feature_enabled('awesome_feature') assert result is True def test_check_feature_set_to_control_is_false(testapp): """Checking a control feature returns false.""" with testapp.test_request_context(): setattr(g, FEATURES_ATTRIBUTE, {'awesome_feature': 'control'}) result = features.is_feature_enabled('awesome_feature') assert result is False def test_feature_engine_loads_and_stores_in_g( testapp, mocker, fixture_service_response): """Engine loads and stores features in g.""" mock_general_features = mocker.patch.object( ows_features, 'general_features', return_value=response.Response( message=fixture_service_response)) with testapp.test_request_context(): engine = features.FeatureEngine() result = engine.load() assert result is True mock_general_features.assert_called_once_with() feature_dict = engine.get() assert feature_dict == fixture_service_response def test_feature_engine_returns_errors( testapp, mocker, fixture_error_response): """Engine returns errors when api call fails.""" mock_general_features = mocker.patch.object( ows_features, 'general_features', return_value=fixture_error_response) with testapp.test_request_context(): engine = features.FeatureEngine() result = engine.load() mock_general_features.assert_called_once_with() assert result is fixture_error_response def test_feature_engine_loads_from_user_features( testapp, mocker, fixture_service_response): """Engine loads using user_features in presence of Orchard-User-Id.""" user = 'dog:fred' mock_user_features = mocker.patch.object( ows_features, 'user_features', return_value=response.Response(message=fixture_service_response)) with testapp.test_request_context( 'does/not/matter', headers={'Orchard-User-Id': user}): engine = features.FeatureEngine() result = engine.load() assert result is True mock_user_features.assert_called_once_with(user) feature_dict = engine.get() assert feature_dict == fixture_service_response def test_load_features_errors_with_feature_engine_load( testapp, mocker, fixture_error_response): """Test decorator returns error with feature_engine load error.""" mock_feature_engine = mocker.patch.object( features.FeatureEngine, 'load', return_value=fixture_error_response) @features.load_features def func(): pass with testapp.test_request_context(): result = func() assert isinstance(result, flask.Response) mock_feature_engine.assert_called_once_with() def test_load_features_calls_feature_engine_load(testapp, mocker): """Test decorator calls feature_engine load.""" mock_feature_engine = mocker.patch.object( features.FeatureEngine, 'load', return_value=True) @features.load_features def func(): pass with testapp.test_request_context(): func() mock_feature_engine.assert_called_once_with() def test_check_feature_enabled(mocker, testapp): """Test that check feature returns True is feature enabled.""" headers = {header.ORCHARD_USER_ID: 'testuser'} spec = { 'service': 'ows-features', 'path': '/features/user/testuser', 'status': 200, 'json': {'test_feature': 'enabled'} } mocker.patch.object( request, 'get', test_utils.mock_ows_requests([spec])) with testapp.test_request_context('/', headers=headers): result = features.check_feature('test_feature') assert result is True def test_check_feature_disabled(mocker, testapp): """Test that check feature returns False is feature disabled.""" headers = {header.ORCHARD_USER_ID: 'testuser'} spec = { 'service': 'ows-features', 'path': '/features/user/testuser', 'status': 200, 'json': {'test_feature': 'control'} } mocker.patch.object( request, 'get', test_utils.mock_ows_requests([spec])) with testapp.test_request_context('/', headers=headers): result = features.check_feature('test_feature') assert result is False def test_check_feature_exception(mocker, testapp): """Test that exception during checking returns false.""" mocker.patch.object(features.feature_engine, 'get', side_effect=Exception) with testapp.test_request_context('/'): # Patch g.ows.log within the app context mock_log = mocker.MagicMock() flask.g.ows = mocker.MagicMock(log=mock_log) sentry = mocker.patch.object(features.sentry_base, 'Raven') result = features.check_feature('test_feature') assert result is False assert mock_log.error.called assert sentry.captureException.called