def create_basic_filter(self, channels=None): if channels: channel_objs = [ChannelFactory(slug=slug) for slug in channels] else: channel_objs = [ChannelFactory()] return filters.ChannelFilter.create( channels=[c.slug for c in channel_objs])
def test_update_recipe_channel(self, api_client): c1 = ChannelFactory(slug='release') c2 = ChannelFactory(slug='beta') r = RecipeFactory(channels=[c1]) res = api_client.patch(f'/api/v1/recipe/{r.pk}/', {'channels': ['beta']}) assert res.status_code == 200 r.refresh_from_db() assert list(r.channels.all()) == [c2]
def test_list_filter_channels(self, api_client): r1 = RecipeFactory(channels=[ChannelFactory(slug='beta')]) r2 = RecipeFactory(channels=[ChannelFactory(slug='release')]) res = api_client.get('/api/v1/recipe/?channels=beta') assert res.status_code == 200 assert len(res.data) == 1 assert res.data[0]['id'] == r1.id res = api_client.get('/api/v1/recipe/?channels=beta,release') assert res.status_code == 200 assert len(res.data) == 2 for recipe in res.data: assert recipe['id'] in [r1.id, r2.id]
def test_it_works(self, rf): channel = ChannelFactory() country = CountryFactory() locale = LocaleFactory() recipe = RecipeFactory(arguments={'foo': 'bar'}, channels=[channel], countries=[country], locales=[locale]) action = recipe.action serializer = RecipeSerializer(recipe, context={'request': rf.get('/')}) assert serializer.data == { 'name': recipe.name, 'id': recipe.id, 'last_updated': Whatever(), 'enabled': recipe.enabled, 'extra_filter_expression': recipe.extra_filter_expression, 'filter_expression': recipe.filter_expression, 'revision_id': recipe.revision_id, 'action': action.name, 'arguments': { 'foo': 'bar', }, 'channels': [channel.slug], 'countries': [country.code], 'locales': [locale.code] }
def test_canonical_json(self): recipe = RecipeFactory( action=ActionFactory(name='action'), arguments_json='{"foo": 1, "bar": 2}', channels=[ChannelFactory(slug='beta')], countries=[CountryFactory(code='CA')], enabled=False, extra_filter_expression='2 + 2 == 4', locales=[LocaleFactory(code='en-US')], name='canonical', ) # Yes, this is really ugly, but we really do need to compare an exact # byte sequence, since this is used for hashing and signing filter_expression = ( "(normandy.locale in ['en-US']) && (normandy.country in ['CA']) && " "(normandy.channel in ['beta']) && (2 + 2 == 4)") expected = ('{' '"action":"action",' '"arguments":{"bar":2,"foo":1},' '"enabled":false,' '"filter_expression":"%(filter_expression)s",' '"id":%(id)s,' '"is_approved":false,' '"last_updated":"%(last_updated)s",' '"name":"canonical",' '"revision_id":"%(revision_id)s"' '}') % { 'id': recipe.id, 'revision_id': recipe.revision_id, 'last_updated': recipe.last_updated.strftime('%Y-%m-%dT%H:%M:%S.%fZ'), 'filter_expression': filter_expression } expected = expected.encode() assert recipe.canonical_json() == expected
def test_recipe_revise_channels(self): c1 = ChannelFactory(slug='beta') recipe = RecipeFactory(channels=[c1]) c2 = ChannelFactory(slug='release') recipe.revise(channels=[c2]) assert recipe.channels.count() == 1 assert list(recipe.channels.all()) == [c2] recipe.revise(channels=[c1, c2]) channels = list(recipe.channels.all()) assert recipe.channels.count() == 2 assert c1 in channels assert c2 in channels recipe.revise(channels=[]) assert recipe.channels.count() == 0
def test_recipe_doesnt_revise_when_clean(self): channel = ChannelFactory() recipe = RecipeFactory(name='my name', channels=[channel]) revision_id = recipe.revision_id last_updated = recipe.last_updated recipe.revise(name='my name', channels=[channel]) assert revision_id == recipe.revision_id assert last_updated == recipe.last_updated
def test_validation_with_valid_data(self): mockAction = ActionFactory(name='show-heartbeat', arguments_schema=ARGUMENTS_SCHEMA) channel = ChannelFactory(slug='release') country = CountryFactory(code='CA') locale = LocaleFactory(code='en-US') serializer = RecipeSerializer( data={ 'name': 'bar', 'enabled': True, 'extra_filter_expression': '[]', 'action': 'show-heartbeat', 'channels': ['release'], 'countries': ['CA'], 'locales': ['en-US'], 'arguments': { 'surveyId': 'lorem-ipsum-dolor', 'surveys': [{ 'title': 'adipscing', 'weight': 1 }, { 'title': 'consequetar', 'weight': 1 }] } }) assert serializer.is_valid() assert serializer.validated_data == { 'name': 'bar', 'enabled': True, 'extra_filter_expression': '[]', 'action': mockAction, 'arguments': { 'surveyId': 'lorem-ipsum-dolor', 'surveys': [{ 'title': 'adipscing', 'weight': 1 }, { 'title': 'consequetar', 'weight': 1 }] }, 'channels': [channel], 'countries': [country], 'locales': [locale], } assert serializer.errors == {}
def test_filter_expression(self): channel1 = ChannelFactory(slug='beta', name='Beta') channel2 = ChannelFactory(slug='release', name='Release') country1 = CountryFactory(code='US', name='USA') country2 = CountryFactory(code='CA', name='Canada') locale1 = LocaleFactory(code='en-US', name='English (US)') locale2 = LocaleFactory(code='fr-CA', name='French (CA)') r = RecipeFactory() assert r.filter_expression == '' r = RecipeFactory(channels=[channel1]) assert r.filter_expression == "normandy.channel in ['beta']" r.revise(channels=[channel1, channel2]) assert r.filter_expression == "normandy.channel in ['beta', 'release']" r = RecipeFactory(countries=[country1]) assert r.filter_expression == "normandy.country in ['US']" r.revise(countries=[country1, country2]) assert r.filter_expression == "normandy.country in ['CA', 'US']" r = RecipeFactory(locales=[locale1]) assert r.filter_expression == "normandy.locale in ['en-US']" r.revise(locales=[locale1, locale2]) assert r.filter_expression == "normandy.locale in ['en-US', 'fr-CA']" r = RecipeFactory(extra_filter_expression='2 + 2 == 4') assert r.filter_expression == '2 + 2 == 4' r.revise(channels=[channel1], countries=[country1], locales=[locale1]) assert r.filter_expression == ("(normandy.locale in ['en-US']) && " "(normandy.country in ['US']) && " "(normandy.channel in ['beta']) && " "(2 + 2 == 4)")
def test_recipe_revise_partial(self): a1 = ActionFactory() recipe = RecipeFactory( name='unchanged', action=a1, arguments={'message': 'something'}, extra_filter_expression='something !== undefined') a2 = ActionFactory() c = ChannelFactory(slug='beta') recipe.revise(name='changed', action=a2, channels=[c]) assert recipe.action == a2 assert recipe.name == 'changed' assert recipe.arguments == {'message': 'something'} assert recipe.filter_expression == ( "(normandy.channel in ['beta']) && " "(something !== undefined)")
def test_it_works(self, rf): channel = ChannelFactory() country = CountryFactory() locale = LocaleFactory() recipe = RecipeFactory(arguments={'foo': 'bar'}, channels=[channel], countries=[country], locales=[locale]) approval = ApprovalRequestFactory(revision=recipe.latest_revision) action = recipe.action serializer = RecipeSerializer(recipe, context={'request': rf.get('/')}) assert serializer.data == { 'name': recipe.name, 'id': recipe.id, 'last_updated': Whatever(), 'enabled': recipe.enabled, 'extra_filter_expression': recipe.extra_filter_expression, 'filter_expression': recipe.filter_expression, 'action': { 'arguments_schema': {}, 'id': action.id, 'implementation_url': Whatever(), 'name': action.name, }, 'arguments': { 'foo': 'bar', }, 'channels': [channel.slug], 'countries': [country.code], 'locales': [locale.code], 'is_approved': False, 'latest_revision': RecipeRevisionSerializer(recipe.latest_revision).data, 'approved_revision': None, 'approval_request': { 'id': approval.id, 'created': Whatever(), 'creator': Whatever(), 'approved': None, 'approver': None, 'comment': None, }, }