Skip to content

Commit

Permalink
feat: Allow override_flag testutil to set different checks
Browse files Browse the repository at this point in the history
Up until now, the `override_flag` test util was only useful to
completely activate or deactivate a flag. It didn't allow to provide
more customization for all the internal checks it makes, like evaluating
if the request user is authenticated or staff.

This change provides that functionality, without breaking the current
API, to avoid breaking changes. Now, users can provide more granular
arguments to `override_flag`, for a more flexible flag testing.

Closes jazzband#439.
  • Loading branch information
adamantike committed Dec 2, 2022
1 parent 1d7a097 commit 1f193b9
Show file tree
Hide file tree
Showing 3 changed files with 398 additions and 7 deletions.
11 changes: 11 additions & 0 deletions docs/testing/automated.rst
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,17 @@ Or::
# samples behave normally.
assert waffle.sample_is_active('sample_name')

``override_flag`` also allows providing values for its different checks.
For example::

@override_flag('flag_name', percent=25)
def test_with_flag():
...

@override_flag('flag_name', staff=True, superusers=True)
def test_with_flag():
...

All three will restore the relevant flag, sample, or switch to its
previous state: they will restore the old values and will delete objects
that did not exist.
Expand Down
250 changes: 248 additions & 2 deletions waffle/tests/test_testutils.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import contextlib
import random
from decimal import Decimal
from unittest import mock

from django.contrib.auth import get_user_model
from django.contrib.auth.models import AnonymousUser
from django.db import transaction
from django.test import TransactionTestCase, RequestFactory, TestCase
from django.test import RequestFactory, TestCase, TransactionTestCase

import waffle
from waffle.testutils import override_switch, override_flag, override_sample
from waffle.testutils import override_flag, override_sample, override_switch


class OverrideSwitchMixin:
Expand Down Expand Up @@ -116,6 +120,14 @@ def req():
return r


@contextlib.contextmanager
def provide_user(**kwargs):
user = get_user_model()(**kwargs)
user.save()
yield user
user.delete()


class OverrideFlagTestsMixin:
def test_flag_existed_and_was_active(self):
waffle.get_waffle_flag_model().objects.create(name='foo', everyone=True)
Expand Down Expand Up @@ -173,6 +185,240 @@ def test_cache_is_flushed_by_testutils_even_in_transaction(self):

assert waffle.flag_is_active(req(), 'foo')

@mock.patch.object(random, 'uniform')
def test_flag_existed_and_was_active_for_percent(self, uniform):
waffle.get_waffle_flag_model().objects.create(name='foo', everyone=None, percent='50')

uniform.return_value = '75'

with override_flag('foo', percent=80.0):
assert waffle.flag_is_active(req(), 'foo')

with override_flag('foo', percent=40.0):
assert not waffle.flag_is_active(req(), 'foo')

assert waffle.get_waffle_flag_model().objects.get(name='foo').percent == Decimal('50')

@mock.patch.object(random, 'uniform')
def test_flag_existed_and_was_inactive_for_percent(self, uniform):
waffle.get_waffle_flag_model().objects.create(name='foo', everyone=None, percent=None)

uniform.return_value = '75'

with override_flag('foo', percent=80.0):
assert waffle.flag_is_active(req(), 'foo')

with override_flag('foo', percent=40.0):
assert not waffle.flag_is_active(req(), 'foo')

assert not waffle.get_waffle_flag_model().objects.get(name='foo').percent

def test_flag_existed_and_was_active_for_testing(self):
waffle.get_waffle_flag_model().objects.create(name='foo', everyone=None, testing=True)

with override_flag('foo', testing=True):
request = req()
request.COOKIES['dwft_foo'] = 'True'
assert waffle.flag_is_active(request, 'foo')
assert not waffle.flag_is_active(req(), 'foo')

with override_flag('foo', testing=False):
request = req()
request.COOKIES['dwft_foo'] = 'True'
assert not waffle.flag_is_active(request, 'foo')
assert not waffle.flag_is_active(req(), 'foo')

assert waffle.get_waffle_flag_model().objects.get(name='foo').testing

def test_flag_existed_and_was_inactive_for_testing(self):
waffle.get_waffle_flag_model().objects.create(name='foo', everyone=None, testing=False)

with override_flag('foo', testing=True):
request = req()
request.COOKIES['dwft_foo'] = 'True'
assert waffle.flag_is_active(request, 'foo')
assert not waffle.flag_is_active(req(), 'foo')

with override_flag('foo', testing=False):
request = req()
request.COOKIES['dwft_foo'] = 'True'
assert not waffle.flag_is_active(request, 'foo')
assert not waffle.flag_is_active(req(), 'foo')

assert not waffle.get_waffle_flag_model().objects.get(name='foo').testing

def test_flag_existed_and_was_active_for_superusers(self):
waffle.get_waffle_flag_model().objects.create(name='foo', everyone=None, superusers=True)

with override_flag('foo', superusers=True):
with provide_user(username='foo', is_superuser=True) as user:
request = req()
request.user = user
assert waffle.flag_is_active(request, 'foo')
with provide_user(username='foo', is_superuser=False) as user:
request = req()
request.user = user
assert not waffle.flag_is_active(request, 'foo')

with override_flag('foo', superusers=False):
with provide_user(username='foo', is_superuser=True) as user:
request = req()
request.user = user
assert not waffle.flag_is_active(request, 'foo')
with provide_user(username='foo', is_superuser=False) as user:
request = req()
request.user = user
assert not waffle.flag_is_active(request, 'foo')

assert waffle.get_waffle_flag_model().objects.get(name='foo').superusers

def test_flag_existed_and_was_inactive_for_superusers(self):
waffle.get_waffle_flag_model().objects.create(name='foo', everyone=None, superusers=False)

with override_flag('foo', superusers=True):
with provide_user(username='foo', is_superuser=True) as user:
request = req()
request.user = user
assert waffle.flag_is_active(request, 'foo')
with provide_user(username='foo', is_superuser=False) as user:
request = req()
request.user = user
assert not waffle.flag_is_active(request, 'foo')

with override_flag('foo', superusers=False):
with provide_user(username='foo', is_superuser=True) as user:
request = req()
request.user = user
assert not waffle.flag_is_active(request, 'foo')
with provide_user(username='foo', is_superuser=False) as user:
request = req()
request.user = user
assert not waffle.flag_is_active(request, 'foo')

assert not waffle.get_waffle_flag_model().objects.get(name='foo').superusers

def test_flag_existed_and_was_active_for_staff(self):
waffle.get_waffle_flag_model().objects.create(name='foo', everyone=None, staff=True)

with override_flag('foo', staff=True):
with provide_user(username='foo', is_staff=True) as user:
request = req()
request.user = user
assert waffle.flag_is_active(request, 'foo')
with provide_user(username='foo', is_staff=False) as user:
request = req()
request.user = user
assert not waffle.flag_is_active(request, 'foo')

with override_flag('foo', staff=False):
with provide_user(username='foo', is_staff=True) as user:
request = req()
request.user = user
assert not waffle.flag_is_active(request, 'foo')
with provide_user(username='foo', is_staff=False) as user:
request = req()
request.user = user
assert not waffle.flag_is_active(request, 'foo')

assert waffle.get_waffle_flag_model().objects.get(name='foo').staff

def test_flag_existed_and_was_inactive_for_staff(self):
waffle.get_waffle_flag_model().objects.create(name='foo', everyone=None, staff=False)

with override_flag('foo', staff=True):
with provide_user(username='foo', is_staff=True) as user:
request = req()
request.user = user
assert waffle.flag_is_active(request, 'foo')
with provide_user(username='foo', is_staff=False) as user:
request = req()
request.user = user
assert not waffle.flag_is_active(request, 'foo')

with override_flag('foo', staff=False):
with provide_user(username='foo', is_staff=True) as user:
request = req()
request.user = user
assert not waffle.flag_is_active(request, 'foo')
with provide_user(username='foo', is_staff=False) as user:
request = req()
request.user = user
assert not waffle.flag_is_active(request, 'foo')

assert not waffle.get_waffle_flag_model().objects.get(name='foo').staff

def test_flag_existed_and_was_active_for_authenticated(self):
waffle.get_waffle_flag_model().objects.create(name='foo', everyone=None, authenticated=True)

with override_flag('foo', authenticated=True):
with provide_user(username='foo') as user:
request = req()
request.user = user
assert waffle.flag_is_active(request, 'foo')
assert not waffle.flag_is_active(req(), 'foo')

with override_flag('foo', authenticated=False):
with provide_user(username='foo') as user:
request = req()
request.user = user
assert not waffle.flag_is_active(request, 'foo')
assert not waffle.flag_is_active(req(), 'foo')

assert waffle.get_waffle_flag_model().objects.get(name='foo').authenticated

def test_flag_existed_and_was_inactive_for_authenticated(self):
waffle.get_waffle_flag_model().objects.create(name='foo', everyone=None, authenticated=False)

with override_flag('foo', authenticated=True):
with provide_user(username='foo') as user:
request = req()
request.user = user
assert waffle.flag_is_active(request, 'foo')
assert not waffle.flag_is_active(req(), 'foo')

with override_flag('foo', authenticated=False):
with provide_user(username='foo') as user:
request = req()
request.user = user
assert not waffle.flag_is_active(request, 'foo')
assert not waffle.flag_is_active(req(), 'foo')

assert not waffle.get_waffle_flag_model().objects.get(name='foo').authenticated

def test_flag_existed_and_was_active_for_languages(self):
waffle.get_waffle_flag_model().objects.create(name='foo', everyone=None, languages="en,es")

with override_flag('foo', languages="en,es"):
request = req()
request.LANGUAGE_CODE = "en"
assert waffle.flag_is_active(request, 'foo')
assert not waffle.flag_is_active(req(), 'foo')

with override_flag('foo', languages=""):
request = req()
request.LANGUAGE_CODE = "en"
assert not waffle.flag_is_active(request, 'foo')
assert not waffle.flag_is_active(req(), 'foo')

assert waffle.get_waffle_flag_model().objects.get(name='foo').languages == "en,es"

def test_flag_existed_and_was_inactive_for_languages(self):
waffle.get_waffle_flag_model().objects.create(name='foo', everyone=None, languages="")

with override_flag('foo', languages="en,es"):
request = req()
request.LANGUAGE_CODE = "en"
assert waffle.flag_is_active(request, 'foo')
assert not waffle.flag_is_active(req(), 'foo')

with override_flag('foo', languages=""):
request = req()
request.LANGUAGE_CODE = "en"
assert not waffle.flag_is_active(request, 'foo')
assert not waffle.flag_is_active(req(), 'foo')

assert waffle.get_waffle_flag_model().objects.get(name='foo').languages == ""


class OverrideFlagsTestCase(OverrideFlagTestsMixin, TestCase):
"""
Expand Down
Loading

0 comments on commit 1f193b9

Please sign in to comment.