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])
示例#2
0
    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]
示例#3
0
    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]
        }
示例#5
0
 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
示例#6
0
    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
示例#7
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 == {}
示例#9
0
    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)")
示例#10
0
 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)")
示例#11
0
    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,
            },
        }