feat(nimbus): Firefox Labs Model and API changes (#11697)
Because - We want to add the fields from the updated `NimbusExperiment` schema to the `NimbusExperiment` model to be available internally. This commit - Updates `NimbusExperiment` model. - Updates `NimbusBranchSerializerDesktop` model. - Updates `v6` and `v8` serializer classes with the above fields. - Generates new db migration for the above fields. Fixes #11556
This commit is contained in:
Родитель
4b23a0ad7d
Коммит
5488b455af
|
@ -4237,6 +4237,18 @@
|
|||
"publishedDate": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"isFirefoxLabsOptIn": {
|
||||
"type": "string",
|
||||
"readOnly": true
|
||||
},
|
||||
"firefoxLabsTitle": {
|
||||
"type": "string",
|
||||
"readOnly": true
|
||||
},
|
||||
"firefoxLabsDescription": {
|
||||
"type": "string",
|
||||
"readOnly": true
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
|
|
|
@ -4249,6 +4249,18 @@
|
|||
"publishedDate": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"isFirefoxLabsOptIn": {
|
||||
"type": "string",
|
||||
"readOnly": true
|
||||
},
|
||||
"firefoxLabsTitle": {
|
||||
"type": "string",
|
||||
"readOnly": true
|
||||
},
|
||||
"firefoxLabsDescription": {
|
||||
"type": "string",
|
||||
"readOnly": true
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
|
|
|
@ -55,10 +55,11 @@ class NimbusBranchSerializer(serializers.ModelSerializer):
|
|||
|
||||
class NimbusBranchSerializerDesktop(NimbusBranchSerializer):
|
||||
feature = serializers.SerializerMethodField()
|
||||
firefoxLabsTitle = serializers.ReadOnlyField(source="firefox_labs_title")
|
||||
|
||||
class Meta:
|
||||
model = NimbusBranch
|
||||
fields = ("slug", "ratio", "feature", "features")
|
||||
fields = ("slug", "ratio", "feature", "features", "firefoxLabsTitle")
|
||||
|
||||
def get_feature(self, obj):
|
||||
return {
|
||||
|
@ -111,6 +112,9 @@ class NimbusExperimentSerializer(serializers.ModelSerializer):
|
|||
localizations = serializers.SerializerMethodField()
|
||||
locales = serializers.SerializerMethodField()
|
||||
publishedDate = serializers.DateTimeField(source="published_date")
|
||||
isFirefoxLabsOptIn = serializers.ReadOnlyField(source="is_firefox_labs_opt_in")
|
||||
firefoxLabsTitle = serializers.ReadOnlyField(source="firefox_labs_title")
|
||||
firefoxLabsDescription = serializers.ReadOnlyField(source="firefox_labs_description")
|
||||
|
||||
class Meta:
|
||||
model = NimbusExperiment
|
||||
|
@ -143,6 +147,9 @@ class NimbusExperimentSerializer(serializers.ModelSerializer):
|
|||
"localizations",
|
||||
"locales",
|
||||
"publishedDate",
|
||||
"isFirefoxLabsOptIn",
|
||||
"firefoxLabsTitle",
|
||||
"firefoxLabsDescription",
|
||||
)
|
||||
|
||||
def get_application(self, obj):
|
||||
|
|
|
@ -55,10 +55,11 @@ class NimbusBranchSerializer(serializers.ModelSerializer):
|
|||
|
||||
class NimbusBranchSerializerDesktop(NimbusBranchSerializer):
|
||||
feature = serializers.SerializerMethodField()
|
||||
firefoxLabsTitle = serializers.ReadOnlyField(source="firefox_labs_title")
|
||||
|
||||
class Meta:
|
||||
model = NimbusBranch
|
||||
fields = ("slug", "ratio", "feature", "features")
|
||||
fields = ("slug", "ratio", "feature", "features", "firefoxLabsTitle")
|
||||
|
||||
def get_feature(self, obj):
|
||||
return {
|
||||
|
@ -112,6 +113,9 @@ class NimbusExperimentSerializer(serializers.ModelSerializer):
|
|||
localizations = serializers.SerializerMethodField()
|
||||
locales = serializers.SerializerMethodField()
|
||||
publishedDate = serializers.DateTimeField(source="published_date")
|
||||
isFirefoxLabsOptIn = serializers.ReadOnlyField(source="is_firefox_labs_opt_in")
|
||||
firefoxLabsTitle = serializers.ReadOnlyField(source="firefox_labs_title")
|
||||
firefoxLabsDescription = serializers.ReadOnlyField(source="firefox_labs_description")
|
||||
|
||||
class Meta:
|
||||
model = NimbusExperiment
|
||||
|
@ -145,6 +149,9 @@ class NimbusExperimentSerializer(serializers.ModelSerializer):
|
|||
"localizations",
|
||||
"locales",
|
||||
"publishedDate",
|
||||
"isFirefoxLabsOptIn",
|
||||
"firefoxLabsTitle",
|
||||
"firefoxLabsDescription",
|
||||
)
|
||||
|
||||
def get_application(self, obj):
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
# Generated by Django 5.1.1 on 2024-11-05 21:25
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("experiments", "0273_nimbusexperiment_segments"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="nimbusbranch",
|
||||
name="firefox_labs_title",
|
||||
field=models.TextField(
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name="An optional string containing the Fluent ID for the title of the opt-in",
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="nimbusexperiment",
|
||||
name="firefox_labs_description",
|
||||
field=models.TextField(
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name="An optional string containing the Fluent ID for the description of the opt-in",
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="nimbusexperiment",
|
||||
name="firefox_labs_title",
|
||||
field=models.TextField(
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name="An optional string containing the Fluent ID for the title of the opt-in",
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="nimbusexperiment",
|
||||
name="is_firefox_labs_opt_in",
|
||||
field=models.BooleanField(
|
||||
default=False, verbose_name="Is Experiment a Firefox Labs opt-n"
|
||||
),
|
||||
),
|
||||
]
|
|
@ -370,6 +370,20 @@ class NimbusExperiment(NimbusConstants, TargetingConstants, FilterMixin, models.
|
|||
)
|
||||
use_group_id = models.BooleanField(default=False)
|
||||
objects = NimbusExperimentManager()
|
||||
is_firefox_labs_opt_in = models.BooleanField(
|
||||
"Is Experiment a Firefox Labs opt-n", default=False
|
||||
)
|
||||
firefox_labs_title = models.TextField(
|
||||
"An optional string containing the Fluent ID for the title of the opt-in",
|
||||
blank=True,
|
||||
null=True,
|
||||
)
|
||||
firefox_labs_description = models.TextField(
|
||||
"An optional string containing the Fluent ID "
|
||||
"for the description of the opt-in",
|
||||
blank=True,
|
||||
null=True,
|
||||
)
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Nimbus Experiment"
|
||||
|
@ -1356,6 +1370,11 @@ class NimbusBranch(models.Model):
|
|||
slug = models.SlugField(max_length=NimbusConstants.MAX_SLUG_LEN, null=False)
|
||||
description = models.TextField(blank=True, default="")
|
||||
ratio = models.PositiveIntegerField(default=1)
|
||||
firefox_labs_title = models.TextField(
|
||||
"An optional string containing the Fluent ID for the title of the opt-in",
|
||||
blank=True,
|
||||
null=True,
|
||||
)
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Nimbus Branch"
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import datetime
|
||||
import json
|
||||
from typing import Any
|
||||
|
||||
from django.conf import settings
|
||||
from django.test import TestCase
|
||||
|
@ -36,6 +37,9 @@ class TestNimbusExperimentSerializer(TestCase):
|
|||
secondary_outcomes=["quux", "xyzzy"],
|
||||
locales=[locale_en_us],
|
||||
_enrollment_end_date=datetime.date(2022, 1, 5),
|
||||
is_firefox_labs_opt_in=False,
|
||||
firefox_labs_title=None,
|
||||
firefox_labs_description=None,
|
||||
)
|
||||
serializer = NimbusExperimentSerializer(experiment)
|
||||
experiment_data = serializer.data.copy()
|
||||
|
@ -48,6 +52,10 @@ class TestNimbusExperimentSerializer(TestCase):
|
|||
assert experiment.end_date
|
||||
|
||||
min_required_version = NimbusExperiment.MIN_REQUIRED_VERSION
|
||||
expected_experiment_data = self._experiment_data_without_branches_and_featureIds(
|
||||
experiment, min_required_version
|
||||
)
|
||||
self.assertDictEqual(experiment_data, expected_experiment_data)
|
||||
|
||||
self.assertDictEqual(
|
||||
experiment_data,
|
||||
|
@ -92,6 +100,9 @@ class TestNimbusExperimentSerializer(TestCase):
|
|||
"localizations": None,
|
||||
"locales": ["en-US"],
|
||||
"publishedDate": experiment.published_date,
|
||||
"isFirefoxLabsOptIn": False,
|
||||
"firefoxLabsTitle": None,
|
||||
"firefoxLabsDescription": None,
|
||||
},
|
||||
)
|
||||
|
||||
|
@ -129,12 +140,56 @@ class TestNimbusExperimentSerializer(TestCase):
|
|||
}
|
||||
for fv in branch.feature_values.all()
|
||||
],
|
||||
"firefoxLabsTitle": branch.firefox_labs_title,
|
||||
},
|
||||
branches_data,
|
||||
)
|
||||
|
||||
NimbusExperimentSchema.model_validate(serializer.data)
|
||||
|
||||
def test_expected_schema_with_desktop_with_non_default_fxlabs_fields(self):
|
||||
locale_en_us = LocaleFactory.create(code="en-US")
|
||||
application = NimbusExperiment.Application.DESKTOP
|
||||
feature1 = NimbusFeatureConfigFactory.create(application=application)
|
||||
feature2 = NimbusFeatureConfigFactory.create(application=application)
|
||||
experiment = NimbusExperimentFactory.create_with_lifecycle(
|
||||
NimbusExperimentFactory.Lifecycles.ENDING_APPROVE_APPROVE,
|
||||
application=application,
|
||||
firefox_min_version=NimbusExperiment.MIN_REQUIRED_VERSION,
|
||||
feature_configs=[feature1, feature2],
|
||||
targeting_config_slug=NimbusExperiment.TargetingConfig.NO_TARGETING,
|
||||
channel=NimbusExperiment.Channel.NIGHTLY,
|
||||
primary_outcomes=["foo", "bar", "baz"],
|
||||
secondary_outcomes=["quux", "xyzzy"],
|
||||
segments=["segment1", "segment2"],
|
||||
locales=[locale_en_us],
|
||||
_enrollment_end_date=datetime.date(2022, 1, 5),
|
||||
is_firefox_labs_opt_in=True,
|
||||
firefox_labs_title="test-fx-labs-title",
|
||||
firefox_labs_description="test-fx-labs-description",
|
||||
)
|
||||
serializer = NimbusExperimentSerializer(experiment)
|
||||
experiment_data = serializer.data.copy()
|
||||
min_required_version = NimbusExperiment.MIN_REQUIRED_VERSION
|
||||
|
||||
expected_experiment_data = self._experiment_data_without_branches_and_featureIds(
|
||||
experiment, min_required_version
|
||||
)
|
||||
expected_experiment_data.update(
|
||||
{
|
||||
"isFirefoxLabsOptIn": True,
|
||||
"firefoxLabsTitle": "test-fx-labs-title",
|
||||
"firefoxLabsDescription": "test-fx-labs-description",
|
||||
}
|
||||
)
|
||||
|
||||
# popping these since this test is not asserting on these
|
||||
experiment_data.pop("bucketConfig")
|
||||
experiment_data.pop("branches")
|
||||
experiment_data.pop("featureIds")
|
||||
|
||||
self.assertDictEqual(experiment_data, expected_experiment_data)
|
||||
|
||||
def test_enrollment_end_date_none_while_live_enrolling(self):
|
||||
locale_en_us = LocaleFactory.create(code="en-US")
|
||||
application = NimbusExperiment.Application.DESKTOP
|
||||
|
@ -370,3 +425,52 @@ class TestNimbusExperimentSerializer(TestCase):
|
|||
self.assertIsNone(serializer.data["localizations"])
|
||||
else:
|
||||
self.assertEqual(serializer.data["localizations"], expected)
|
||||
|
||||
def _experiment_data_without_branches_and_featureIds(
|
||||
self, experiment_data, min_required_version
|
||||
) -> dict[str, Any]:
|
||||
return {
|
||||
"arguments": {},
|
||||
"application": "firefox-desktop",
|
||||
"appName": "firefox_desktop",
|
||||
"appId": "firefox-desktop",
|
||||
"channel": "nightly",
|
||||
# DRF manually replaces the isoformat suffix so we have to do the same
|
||||
"startDate": experiment_data.start_date.isoformat().replace("+00:00", "Z"),
|
||||
"enrollmentEndDate": (
|
||||
experiment_data.actual_enrollment_end_date.isoformat().replace(
|
||||
"+00:00", "Z"
|
||||
)
|
||||
),
|
||||
"endDate": experiment_data.end_date.isoformat().replace("+00:00", "Z"),
|
||||
"id": experiment_data.slug,
|
||||
"isEnrollmentPaused": True,
|
||||
"isRollout": False,
|
||||
"proposedDuration": experiment_data.proposed_duration,
|
||||
"proposedEnrollment": experiment_data.proposed_enrollment,
|
||||
"referenceBranch": experiment_data.reference_branch.slug,
|
||||
"schemaVersion": settings.NIMBUS_SCHEMA_VERSION,
|
||||
"slug": experiment_data.slug,
|
||||
"targeting": (
|
||||
f'(browserSettings.update.channel == "nightly") '
|
||||
f"&& (version|versionCompare('{min_required_version}') >= 0) "
|
||||
f"&& (locale in ['en-US'])"
|
||||
),
|
||||
"userFacingDescription": experiment_data.public_description,
|
||||
"userFacingName": experiment_data.name,
|
||||
"probeSets": [],
|
||||
"outcomes": [
|
||||
{"priority": "primary", "slug": "foo"},
|
||||
{"priority": "primary", "slug": "bar"},
|
||||
{"priority": "primary", "slug": "baz"},
|
||||
{"priority": "secondary", "slug": "quux"},
|
||||
{"priority": "secondary", "slug": "xyzzy"},
|
||||
],
|
||||
"featureValidationOptOut": experiment_data.is_client_schema_disabled,
|
||||
"localizations": None,
|
||||
"locales": ["en-US"],
|
||||
"publishedDate": experiment_data.published_date,
|
||||
"isFirefoxLabsOptIn": False,
|
||||
"firefoxLabsTitle": None,
|
||||
"firefoxLabsDescription": None,
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import datetime
|
||||
import json
|
||||
from typing import Any
|
||||
|
||||
from django.conf import settings
|
||||
from django.test import TestCase
|
||||
|
@ -37,6 +38,9 @@ class TestNimbusExperimentSerializer(TestCase):
|
|||
segments=["segment1", "segment2"],
|
||||
locales=[locale_en_us],
|
||||
_enrollment_end_date=datetime.date(2022, 1, 5),
|
||||
is_firefox_labs_opt_in=False,
|
||||
firefox_labs_title=None,
|
||||
firefox_labs_description=None,
|
||||
)
|
||||
serializer = NimbusExperimentSerializer(experiment)
|
||||
experiment_data = serializer.data.copy()
|
||||
|
@ -49,53 +53,10 @@ class TestNimbusExperimentSerializer(TestCase):
|
|||
assert experiment.end_date
|
||||
|
||||
min_required_version = NimbusExperiment.MIN_REQUIRED_VERSION
|
||||
|
||||
self.assertDictEqual(
|
||||
experiment_data,
|
||||
{
|
||||
"arguments": {},
|
||||
"application": "firefox-desktop",
|
||||
"appName": "firefox_desktop",
|
||||
"appId": "firefox-desktop",
|
||||
"channel": "nightly",
|
||||
# DRF manually replaces the isoformat suffix so we have to do the same
|
||||
"startDate": experiment.start_date.isoformat().replace("+00:00", "Z"),
|
||||
"enrollmentEndDate": (
|
||||
experiment.actual_enrollment_end_date.isoformat().replace(
|
||||
"+00:00", "Z"
|
||||
)
|
||||
),
|
||||
"endDate": experiment.end_date.isoformat().replace("+00:00", "Z"),
|
||||
"id": experiment.slug,
|
||||
"isEnrollmentPaused": True,
|
||||
"isRollout": False,
|
||||
"proposedDuration": experiment.proposed_duration,
|
||||
"proposedEnrollment": experiment.proposed_enrollment,
|
||||
"referenceBranch": experiment.reference_branch.slug,
|
||||
"schemaVersion": settings.NIMBUS_SCHEMA_VERSION,
|
||||
"slug": experiment.slug,
|
||||
"targeting": (
|
||||
f'(browserSettings.update.channel == "nightly") '
|
||||
f"&& (version|versionCompare('{min_required_version}') >= 0) "
|
||||
f"&& (locale in ['en-US'])"
|
||||
),
|
||||
"userFacingDescription": experiment.public_description,
|
||||
"userFacingName": experiment.name,
|
||||
"probeSets": [],
|
||||
"outcomes": [
|
||||
{"priority": "primary", "slug": "foo"},
|
||||
{"priority": "primary", "slug": "bar"},
|
||||
{"priority": "primary", "slug": "baz"},
|
||||
{"priority": "secondary", "slug": "quux"},
|
||||
{"priority": "secondary", "slug": "xyzzy"},
|
||||
],
|
||||
"segments": [{"slug": "segment1"}, {"slug": "segment2"}],
|
||||
"featureValidationOptOut": experiment.is_client_schema_disabled,
|
||||
"localizations": None,
|
||||
"locales": ["en-US"],
|
||||
"publishedDate": experiment.published_date,
|
||||
},
|
||||
expected_experiment_data = self._experiment_data_without_branches_and_featureIds(
|
||||
experiment, min_required_version
|
||||
)
|
||||
self.assertDictEqual(experiment_data, expected_experiment_data)
|
||||
|
||||
self.assertEqual(set(feature_ids_data), {feature1.slug, feature2.slug})
|
||||
|
||||
|
@ -131,12 +92,56 @@ class TestNimbusExperimentSerializer(TestCase):
|
|||
}
|
||||
for fv in branch.feature_values.all()
|
||||
],
|
||||
"firefoxLabsTitle": branch.firefox_labs_title,
|
||||
},
|
||||
branches_data,
|
||||
)
|
||||
|
||||
NimbusExperimentSchema.model_validate(serializer.data)
|
||||
|
||||
def test_expected_schema_with_desktop_with_non_default_fxlabs_fields(self):
|
||||
locale_en_us = LocaleFactory.create(code="en-US")
|
||||
application = NimbusExperiment.Application.DESKTOP
|
||||
feature1 = NimbusFeatureConfigFactory.create(application=application)
|
||||
feature2 = NimbusFeatureConfigFactory.create(application=application)
|
||||
experiment = NimbusExperimentFactory.create_with_lifecycle(
|
||||
NimbusExperimentFactory.Lifecycles.ENDING_APPROVE_APPROVE,
|
||||
application=application,
|
||||
firefox_min_version=NimbusExperiment.MIN_REQUIRED_VERSION,
|
||||
feature_configs=[feature1, feature2],
|
||||
targeting_config_slug=NimbusExperiment.TargetingConfig.NO_TARGETING,
|
||||
channel=NimbusExperiment.Channel.NIGHTLY,
|
||||
primary_outcomes=["foo", "bar", "baz"],
|
||||
secondary_outcomes=["quux", "xyzzy"],
|
||||
segments=["segment1", "segment2"],
|
||||
locales=[locale_en_us],
|
||||
_enrollment_end_date=datetime.date(2022, 1, 5),
|
||||
is_firefox_labs_opt_in=True,
|
||||
firefox_labs_title="test-fx-labs-title",
|
||||
firefox_labs_description="test-fx-labs-description",
|
||||
)
|
||||
serializer = NimbusExperimentSerializer(experiment)
|
||||
experiment_data = serializer.data.copy()
|
||||
min_required_version = NimbusExperiment.MIN_REQUIRED_VERSION
|
||||
|
||||
expected_experiment_data = self._experiment_data_without_branches_and_featureIds(
|
||||
experiment, min_required_version
|
||||
)
|
||||
expected_experiment_data.update(
|
||||
{
|
||||
"isFirefoxLabsOptIn": True,
|
||||
"firefoxLabsTitle": "test-fx-labs-title",
|
||||
"firefoxLabsDescription": "test-fx-labs-description",
|
||||
}
|
||||
)
|
||||
|
||||
# popping these since this test is not asserting on these
|
||||
experiment_data.pop("bucketConfig")
|
||||
experiment_data.pop("branches")
|
||||
experiment_data.pop("featureIds")
|
||||
|
||||
self.assertDictEqual(experiment_data, expected_experiment_data)
|
||||
|
||||
def test_enrollment_end_date_none_while_live_enrolling(self):
|
||||
locale_en_us = LocaleFactory.create(code="en-US")
|
||||
application = NimbusExperiment.Application.DESKTOP
|
||||
|
@ -374,3 +379,53 @@ class TestNimbusExperimentSerializer(TestCase):
|
|||
self.assertIsNone(serializer.data["localizations"])
|
||||
else:
|
||||
self.assertEqual(serializer.data["localizations"], expected)
|
||||
|
||||
def _experiment_data_without_branches_and_featureIds(
|
||||
self, experiment_data, min_required_version
|
||||
) -> dict[str, Any]:
|
||||
return {
|
||||
"arguments": {},
|
||||
"application": "firefox-desktop",
|
||||
"appName": "firefox_desktop",
|
||||
"appId": "firefox-desktop",
|
||||
"channel": "nightly",
|
||||
# DRF manually replaces the isoformat suffix so we have to do the same
|
||||
"startDate": experiment_data.start_date.isoformat().replace("+00:00", "Z"),
|
||||
"enrollmentEndDate": (
|
||||
experiment_data.actual_enrollment_end_date.isoformat().replace(
|
||||
"+00:00", "Z"
|
||||
)
|
||||
),
|
||||
"endDate": experiment_data.end_date.isoformat().replace("+00:00", "Z"),
|
||||
"id": experiment_data.slug,
|
||||
"isEnrollmentPaused": True,
|
||||
"isRollout": False,
|
||||
"proposedDuration": experiment_data.proposed_duration,
|
||||
"proposedEnrollment": experiment_data.proposed_enrollment,
|
||||
"referenceBranch": experiment_data.reference_branch.slug,
|
||||
"schemaVersion": settings.NIMBUS_SCHEMA_VERSION,
|
||||
"slug": experiment_data.slug,
|
||||
"targeting": (
|
||||
f'(browserSettings.update.channel == "nightly") '
|
||||
f"&& (version|versionCompare('{min_required_version}') >= 0) "
|
||||
f"&& (locale in ['en-US'])"
|
||||
),
|
||||
"userFacingDescription": experiment_data.public_description,
|
||||
"userFacingName": experiment_data.name,
|
||||
"probeSets": [],
|
||||
"outcomes": [
|
||||
{"priority": "primary", "slug": "foo"},
|
||||
{"priority": "primary", "slug": "bar"},
|
||||
{"priority": "primary", "slug": "baz"},
|
||||
{"priority": "secondary", "slug": "quux"},
|
||||
{"priority": "secondary", "slug": "xyzzy"},
|
||||
],
|
||||
"segments": [{"slug": "segment1"}, {"slug": "segment2"}],
|
||||
"featureValidationOptOut": experiment_data.is_client_schema_disabled,
|
||||
"localizations": None,
|
||||
"locales": ["en-US"],
|
||||
"publishedDate": experiment_data.published_date,
|
||||
"isFirefoxLabsOptIn": False,
|
||||
"firefoxLabsTitle": None,
|
||||
"firefoxLabsDescription": None,
|
||||
}
|
||||
|
|
|
@ -471,6 +471,9 @@ class NimbusExperimentFactory(factory.django.DjangoModelFactory):
|
|||
qa_status = factory.LazyAttribute(
|
||||
lambda o: random.choice(list(NimbusExperiment.QAStatus)).value
|
||||
)
|
||||
is_firefox_labs_opt_in = factory.LazyAttribute(lambda o: False)
|
||||
firefox_labs_title = factory.LazyAttribute(lambda o: faker.catch_phrase())
|
||||
firefox_labs_description = factory.LazyAttribute(lambda o: faker.catch_phrase())
|
||||
|
||||
class Meta:
|
||||
model = NimbusExperiment
|
||||
|
@ -707,6 +710,7 @@ class NimbusBranchFactory(factory.django.DjangoModelFactory):
|
|||
lambda o: slugify(o.name)[: NimbusExperiment.MAX_SLUG_LEN]
|
||||
)
|
||||
description = factory.LazyAttribute(lambda o: faker.text())
|
||||
firefox_labs_title = factory.LazyAttribute(lambda o: faker.catch_phrase())
|
||||
|
||||
class Meta:
|
||||
model = NimbusBranch
|
||||
|
|
|
@ -58,9 +58,12 @@ class TestNimbusExperimentChangeLogSerializer(TestCase):
|
|||
"feature_configs": [],
|
||||
"firefox_max_version": NimbusExperiment.Version.NO_VERSION,
|
||||
"firefox_min_version": NimbusExperiment.Version.NO_VERSION,
|
||||
"firefox_labs_title": experiment.firefox_labs_title,
|
||||
"firefox_labs_description": experiment.firefox_labs_description,
|
||||
"hypothesis": NimbusExperiment.HYPOTHESIS_DEFAULT,
|
||||
"is_archived": experiment.is_archived,
|
||||
"is_client_schema_disabled": experiment.is_client_schema_disabled,
|
||||
"is_firefox_labs_opt_in": experiment.is_firefox_labs_opt_in,
|
||||
"is_first_run": experiment.is_first_run,
|
||||
"is_localized": experiment.is_localized,
|
||||
"is_paused": False,
|
||||
|
@ -166,9 +169,12 @@ class TestNimbusExperimentChangeLogSerializer(TestCase):
|
|||
"excluded_experiments": [],
|
||||
"firefox_max_version": experiment.firefox_max_version,
|
||||
"firefox_min_version": experiment.firefox_min_version,
|
||||
"firefox_labs_title": experiment.firefox_labs_title,
|
||||
"firefox_labs_description": experiment.firefox_labs_description,
|
||||
"hypothesis": experiment.hypothesis,
|
||||
"is_archived": experiment.is_archived,
|
||||
"is_client_schema_disabled": experiment.is_client_schema_disabled,
|
||||
"is_firefox_labs_opt_in": experiment.is_firefox_labs_opt_in,
|
||||
"is_first_run": experiment.is_first_run,
|
||||
"is_localized": experiment.is_localized,
|
||||
"is_paused": experiment.is_paused,
|
||||
|
@ -268,6 +274,7 @@ class TestNimbusExperimentChangeLogSerializer(TestCase):
|
|||
"feature_config": experiment.feature_configs.get().id,
|
||||
}
|
||||
],
|
||||
"firefox_labs_title": experiment.reference_branch.firefox_labs_title,
|
||||
},
|
||||
)
|
||||
|
||||
|
@ -285,6 +292,7 @@ class TestNimbusExperimentChangeLogSerializer(TestCase):
|
|||
"feature_config": experiment.feature_configs.get().id,
|
||||
}
|
||||
],
|
||||
"firefox_labs_title": branch.firefox_labs_title,
|
||||
},
|
||||
branches_data,
|
||||
)
|
||||
|
|
Загрузка…
Ссылка в новой задаче