Skip to content
This repository was archived by the owner on Oct 5, 2023. It is now read-only.

Commit 5bcc302

Browse files
authored
Add cookie overriding/adding (#26)
* Add cookie overriding/adding * Black * Clearout migrations * Ensure cookie overriding only works in debug mode * Add test for when cookies are not present * Edit text
1 parent 7409e0f commit 5bcc302

File tree

7 files changed

+111
-23
lines changed

7 files changed

+111
-23
lines changed

django_google_optimize/admin.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
from django.contrib import admin
22

3-
from .models import ExperimentVariant, GoogleExperiment
3+
from .models import ExperimentCookie, ExperimentVariant, GoogleExperiment
4+
5+
6+
class ExperimentCookieInline(admin.StackedInline):
7+
model = ExperimentCookie
48

59

610
class ExperimentVariantInline(admin.StackedInline):
@@ -13,6 +17,4 @@ class GoogleExperimentAdmin(admin.ModelAdmin):
1317
"experiment_id",
1418
"experiment_alias",
1519
)
16-
inlines = [
17-
ExperimentVariantInline,
18-
]
20+
inlines = [ExperimentVariantInline, ExperimentCookieInline]

django_google_optimize/migrations/0001_initial.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Generated by Django 3.0.2 on 2020-01-28 16:33
1+
# Generated by Django 3.0.2 on 2020-01-29 07:56
22

33
from django.db import migrations, models
44
import django.db.models.deletion
@@ -30,6 +30,15 @@ class Migration(migrations.Migration):
3030
('experiment', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='experiment_variant', to='django_google_optimize.GoogleExperiment')),
3131
],
3232
),
33+
migrations.CreateModel(
34+
name='ExperimentCookie',
35+
fields=[
36+
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
37+
('active_variant_index', models.IntegerField(help_text='Overrides or adds the cookie and sets the active variant for this experiment\nNOTE: ONLY WORKS IN DEBUG MODE')),
38+
('active', models.BooleanField()),
39+
('experiment', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='experiment_cookie', to='django_google_optimize.GoogleExperiment')),
40+
],
41+
),
3342
migrations.AddConstraint(
3443
model_name='experimentvariant',
3544
constraint=models.UniqueConstraint(fields=('alias', 'experiment'), name='Can not have the same alias within an experiment_variant'),

django_google_optimize/models.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,18 @@ class Meta:
3131
name="Can not have the same index within an experiment_variant",
3232
),
3333
]
34+
35+
36+
class ExperimentCookie(models.Model):
37+
active_variant_index = models.IntegerField(
38+
# pylint: disable=line-too-long
39+
help_text="Overrides or adds the cookie and sets the active variant for this experiment\nNOTE: ONLY WORKS IN DEBUG MODE"
40+
)
41+
active = models.BooleanField()
42+
experiment = models.OneToOneField(
43+
GoogleExperiment,
44+
null=True,
45+
blank=True,
46+
on_delete=models.CASCADE,
47+
related_name="experiment_cookie",
48+
)

django_google_optimize/utils.py

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import logging
22

3-
from .models import GoogleExperiment
3+
from django.conf import settings
4+
5+
from .models import ExperimentCookie, GoogleExperiment
46

57
logger = logging.getLogger()
68

@@ -63,19 +65,25 @@ def get_experiments_variants(request):
6365
return active_experiments
6466

6567

66-
def _parse_experiments(request):
68+
def _parse_experiments(request,):
6769
ga_exp = request.COOKIES.get("_gaexp")
68-
if not ga_exp:
69-
return None
7070

7171
experiment_variations = {}
72-
73-
parts = ga_exp.split(".")
74-
experiments_part = ".".join(parts[2:])
75-
experiments = experiments_part.split("!")
76-
for experiment_str in experiments:
77-
experiment_parts = experiment_str.split(".")
78-
experiment_id = experiment_parts[0]
79-
variation_id = int(experiment_parts[2])
80-
experiment_variations[experiment_id] = variation_id
81-
return experiment_variations
72+
if ga_exp:
73+
parts = ga_exp.split(".")
74+
experiments_part = ".".join(parts[2:])
75+
experiments = experiments_part.split("!")
76+
for experiment_str in experiments:
77+
experiment_parts = experiment_str.split(".")
78+
experiment_id = experiment_parts[0]
79+
variation_id = int(experiment_parts[2])
80+
experiment_variations[experiment_id] = variation_id
81+
if settings.DEBUG:
82+
cookies = ExperimentCookie.objects.filter(active=True)
83+
for cookie in cookies:
84+
experiment_variations[
85+
cookie.experiment.experiment_id
86+
] = cookie.active_variant_index
87+
if experiment_variations:
88+
return experiment_variations
89+
return None

tests/settings.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
from os import path
22

3-
DEBUG = True
4-
53
SECRET_KEY = "very-secret"
64

75
DATABASES = {"default": {"ENGINE": "django.db.backends.sqlite3", "NAME": "db.sqlite3"}}

tests/test_helpers.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import factory
22

3-
from django_google_optimize.models import ExperimentVariant, GoogleExperiment
3+
from django_google_optimize.models import (
4+
ExperimentCookie,
5+
ExperimentVariant,
6+
GoogleExperiment,
7+
)
48

59

610
# pylint: disable=too-few-public-methods
@@ -21,3 +25,12 @@ class Meta:
2125
alias = factory.Faker("city")
2226
index = factory.Faker("pyint")
2327
experiment = factory.SubFactory(GoogleExperimentFactory)
28+
29+
30+
class ExperimentCookieFactory(factory.django.DjangoModelFactory):
31+
class Meta:
32+
model = ExperimentCookie
33+
34+
active_variant_index = factory.Faker("pyint")
35+
active = True
36+
experiment = factory.SubFactory(GoogleExperimentFactory)

tests/test_utils.py

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@
33
import pytest
44
from django.http import HttpRequest
55

6-
from .test_helpers import ExperimentVariantFactory, GoogleExperimentFactory
6+
from .test_helpers import (
7+
ExperimentCookieFactory,
8+
ExperimentVariantFactory,
9+
GoogleExperimentFactory,
10+
)
711

812
from django_google_optimize.utils import _parse_experiments, get_experiments_variants
913

@@ -153,3 +157,42 @@ def test_filters_active_experiments():
153157
request.COOKIES["_gaexp"] = f"GAX1.2.{exp.experiment_id}.18147.{variant.index}"
154158
values = get_experiments_variants(request)
155159
assert values == {exp.experiment_alias: variant.alias}
160+
161+
162+
@pytest.mark.django_db
163+
def test_cookie_override(settings):
164+
settings.DEBUG = True
165+
exp = GoogleExperimentFactory()
166+
variant = ExperimentVariantFactory(index=1, experiment=exp)
167+
ExperimentCookieFactory(active_variant_index=variant.index, experiment=exp)
168+
169+
request = HttpRequest()
170+
request.COOKIES["_gaexp"] = f"GAX1.2.{exp.experiment_id}.18147.5"
171+
172+
values = get_experiments_variants(request)
173+
assert values == {exp.experiment_alias: variant.alias}
174+
175+
176+
@pytest.mark.django_db
177+
def test_cookie_add_new(settings):
178+
settings.DEBUG = True
179+
exp = GoogleExperimentFactory()
180+
variant = ExperimentVariantFactory(index=1, experiment=exp)
181+
ExperimentCookieFactory(active_variant_index=variant.index, experiment=exp)
182+
183+
request = HttpRequest()
184+
values = get_experiments_variants(request)
185+
assert values == {exp.experiment_alias: variant.alias}
186+
187+
188+
@pytest.mark.django_db
189+
def test_cookie_override_only_debug():
190+
exp = GoogleExperimentFactory()
191+
variant = ExperimentVariantFactory(index=1, experiment=exp)
192+
ExperimentCookieFactory(active_variant_index=5, experiment=exp)
193+
194+
request = HttpRequest()
195+
request.COOKIES["_gaexp"] = f"GAX1.2.{exp.experiment_id}.18147.1"
196+
197+
values = get_experiments_variants(request)
198+
assert values == {exp.experiment_alias: variant.alias}

0 commit comments

Comments
 (0)