Browse Source

ref(testutils): Provider better interface for helpers.Feature

Evan Purkhiser 7 years ago
parent
commit
699764314e

+ 3 - 3
src/sentry/testutils/cases.py

@@ -79,12 +79,12 @@ class BaseTestCase(Fixtures, Exam):
     def tasks(self):
         return TaskRunner()
 
-    def feature(self, name, active=True):
+    def feature(self, names):
         """
-        >>> with self.feature('feature:name')
+        >>> with self.feature({'feature:name': True})
         >>>     # ...
         """
-        return Feature(name, active)
+        return Feature(names)
 
     def auth_provider(self, name, cls):
         """

+ 30 - 2
src/sentry/testutils/helpers/features.py

@@ -2,12 +2,40 @@ from __future__ import absolute_import
 
 __all__ = ['Feature']
 
+import six
+import collections
 from contextlib import contextmanager
 from mock import patch
 
 
 @contextmanager
-def Feature(name, active=True):
+def Feature(names):
+    """
+    Control whether a feature is enabled.
+
+    A single feature may be conviniently enabled with
+
+    >>> with Feature('feature-1'):
+    >>>   # Executes with feature-1 enabled
+
+    More advanced enabling / disabling can be done using a dict
+
+    >>> with Feature({'feature-1': True, 'feature-2': False}):
+    >>>   # Executes with feature-1 enabled and feature-2 disabled
+
+    The following two invocations are equivalent:
+
+    >>> with Feature(['feature-1', 'feature-2']):
+    >>>   # execute with both features enabled
+    >>> with Feature({'feature-1': True, 'feature-2': True}):
+    >>>   # execute with both features enabled
+    """
+    if isinstance(names, six.string_types):
+        names = {names: True}
+
+    elif not isinstance(names, collections.Mapping):
+        names = {k: True for k in names}
+
     with patch('sentry.features.has') as features_has:
-        features_has.side_effect = lambda x, *a, **k: active and x == name
+        features_has.side_effect = lambda x, *a, **k: names.get(x, False)
         yield

+ 1 - 1
tests/sentry/api/endpoints/test_group_details.py

@@ -325,7 +325,7 @@ class GroupUpdateTest(APITestCase):
         url = '/api/0/issues/{}/'.format(group.id)
 
         with self.tasks():
-            with self.feature('projects:custom-filters', True):
+            with self.feature('projects:custom-filters'):
                 resp = self.client.put(
                     url, data={
                         'discard': True,

+ 2 - 2
tests/sentry/api/endpoints/test_organization_integration_details.py

@@ -17,7 +17,7 @@ class OrganizationIntegrationDetailsTest(APITestCase):
         integration.add_organization(org.id)
         path = '/api/0/organizations/{}/integrations/{}/'.format(org.slug, integration.id)
 
-        with self.feature('organizations:integrations-v3', True):
+        with self.feature('organizations:integrations-v3'):
             response = self.client.get(path, format='json')
 
         assert response.status_code == 200, response.content
@@ -35,7 +35,7 @@ class OrganizationIntegrationDeleteTest(APITestCase):
         integration.add_organization(org.id)
         path = '/api/0/organizations/{}/integrations/{}/'.format(org.slug, integration.id)
 
-        with self.feature('organizations:integrations-v3', True):
+        with self.feature('organizations:integrations-v3'):
             response = self.client.delete(path, format='json')
 
         assert response.status_code == 204, response.content

+ 1 - 1
tests/sentry/api/endpoints/test_organization_integrations.py

@@ -17,7 +17,7 @@ class OrganizationIntegrationsListTest(APITestCase):
         integration.add_organization(org.id)
         path = '/api/0/organizations/{}/integrations/'.format(org.slug)
 
-        with self.feature('organizations:integrations-v3', True):
+        with self.feature('organizations:integrations-v3'):
             response = self.client.get(path, format='json')
 
         assert response.status_code == 200, response.content

+ 1 - 1
tests/sentry/api/endpoints/test_project_details.py

@@ -212,7 +212,7 @@ class ProjectUpdateTest(APITestCase):
             'filters:releases': '1.*\n2.1.*',
             'filters:error_messages': 'TypeError*\n*: integer division by modulo or zero',
         }
-        with self.feature('projects:custom-inbound-filters', True):
+        with self.feature('projects:custom-inbound-filters'):
             resp = self.client.put(url, data={'options': options})
         assert resp.status_code == 200, resp.content
         project = Project.objects.get(id=project.id)

+ 1 - 1
tests/sentry/api/endpoints/test_project_group_index.py

@@ -1281,7 +1281,7 @@ class GroupUpdateTest(APITestCase):
             group1=group1,
         )
         with self.tasks():
-            with self.feature('projects:custom-filters', True):
+            with self.feature('projects:custom-filters'):
                 response = self.client.put(
                     url, data={
                         'discard': True,

+ 1 - 1
tests/sentry/templatetags/test_sentry_features.py

@@ -27,7 +27,7 @@ class FeaturesTest(TestCase):
         assert '<span>register</span>' in result
 
     def test_disabled(self):
-        with self.feature('auth:register', False):
+        with self.feature({'auth:register': False}):
             result = self.TEMPLATE.render(Context({
                 'request': Mock(),
             }))

+ 1 - 1
tests/sentry/test_event_manager.py

@@ -84,7 +84,7 @@ class EventManagerTest(TransactionTestCase):
         assert event.id
 
         manager = EventManager(self.make_event())
-        with self.feature('projects:sample-events', False):
+        with self.feature({'projects:sample-events': False}):
             event = manager.save(1)
         assert not event.id
 

+ 1 - 1
tests/sentry/web/frontend/test_auth_login.py

@@ -61,7 +61,7 @@ class AuthLoginTest(TestCase):
 
     def test_registration_disabled(self):
         options.set('auth.allow-registration', True)
-        with self.feature('auth:register', False):
+        with self.feature({'auth:register': False}):
             resp = self.client.get(self.path)
             assert resp.context['register_form'] is None
 

Some files were not shown because too many files changed in this diff