def test_validation_with_valid_data(self): mockAction = ActionFactory( name='show-heartbeat', arguments_schema=ARGUMENTS_SCHEMA ) serializer = RecipeSerializer(data={ 'name': 'bar', 'enabled': True, 'filter_expression': '[]', 'action': 'show-heartbeat', '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, 'filter_expression': '[]', 'action': mockAction, 'arguments': { 'surveyId': 'lorem-ipsum-dolor', 'surveys': [ {'title': 'adipscing', 'weight': 1}, {'title': 'consequetar', 'weight': 1} ] } } assert serializer.errors == {}
def test_validation_with_invalid_filter_expression(self): ActionFactory(name='show-heartbeat', arguments_schema=ARGUMENTS_SCHEMA) serializer = RecipeSerializer( data={ 'name': 'bar', 'enabled': True, 'extra_filter_expression': 'inv(-alsid', 'action': 'show-heartbeat', 'arguments': { 'surveyId': 'lorem-ipsum-dolor', 'surveys': [{ 'title': 'adipscing', 'weight': 1 }, { 'title': 'consequetar', 'weight': 1 }] } }) assert not serializer.is_valid() assert serializer.errors['extra_filter_expression'] == [ 'Could not parse expression: inv(-alsid' ]
def test_validation_with_wrong_arguments(self): ActionFactory( name='show-heartbeat', arguments_schema=ARGUMENTS_SCHEMA ) serializer = RecipeSerializer(data={ 'action': 'show-heartbeat', 'arguments': { 'surveyId': '', 'surveys': [ {'title': '', 'weight': 1}, {'title': 'bar', 'weight': 1}, {'title': 'foo', 'weight': 0}, {'title': 'baz', 'weight': 'lorem ipsum'} ] } }) with pytest.raises(serializers.ValidationError): serializer.is_valid(raise_exception=True) assert serializer.errors['arguments'] == { 'surveyId': 'This field may not be blank.', 'surveys': { 0: {'title': 'This field may not be blank.'}, 2: {'weight': '0 is less than the minimum of 1'}, 3: {'weight': '\'lorem ipsum\' is not of type \'integer\''} } }
def test_validation_with_wrong_action(self): serializer = RecipeSerializer(data={ 'action': 'action-that-doesnt-exist', 'arguments': {} }) with pytest.raises(serializers.ValidationError): serializer.is_valid(raise_exception=True) assert serializer.errors['arguments'] == ['Could not find arguments schema.']
def test_validation_with_wrong_action(self): serializer = RecipeSerializer(data={ 'action': 'action-that-doesnt-exist', 'arguments': {} }) with pytest.raises(serializers.ValidationError): serializer.is_valid(raise_exception=True) assert serializer.errors['arguments'] == [ 'Could not find arguments schema.' ]
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_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_validation_with_wrong_arguments(self): ActionFactory(name='show-heartbeat', arguments_schema=ARGUMENTS_SCHEMA) serializer = RecipeSerializer( data={ 'action': 'show-heartbeat', 'arguments': { 'surveyId': '', 'surveys': [{ 'title': '', 'weight': 1 }, { 'title': 'bar', 'weight': 1 }, { 'title': 'foo', 'weight': 0 }, { 'title': 'baz', 'weight': 'lorem ipsum' }] } }) with pytest.raises(serializers.ValidationError): serializer.is_valid(raise_exception=True) assert serializer.errors['arguments'] == { 'surveyId': 'This field may not be blank.', 'surveys': { 0: { 'title': 'This field may not be blank.' }, 2: { 'weight': '0 is less than the minimum of 1' }, 3: { 'weight': '\'lorem ipsum\' is not of type \'integer\'' } } }
def enable(self, request, pk=None): recipe = self.get_object() recipe.enabled = True try: recipe.save() except Recipe.NotApproved as e: return Response({'enabled': str(e)}, status=status.HTTP_409_CONFLICT) return Response(RecipeSerializer(recipe).data)
def test_it_works_with_signature(self, rf): recipe = RecipeFactory(signed=True) context = {'request': rf.get('/')} combined_serializer = SignedRecipeSerializer(instance=recipe, context=context) recipe_serializer = RecipeSerializer(instance=recipe, context=context) # Testing for shape of data, not contents assert combined_serializer.data == { 'signature': { 'signature': Whatever(), 'timestamp': Whatever(), 'x5u': Whatever(), 'public_key': Whatever(), }, 'recipe': recipe_serializer.data, }
def test_it_works(self, rf): recipe = RecipeFactory(arguments={'foo': 'bar'}) action = recipe.action serializer = RecipeSerializer(recipe, context={'request': rf.get('/')}) action_url = reverse('recipes:action-implementation', kwargs={ 'name': action.name, 'impl_hash': action.implementation_hash, }) assert serializer.data == { 'name': recipe.name, 'id': recipe.id, 'revision_id': recipe.revision_id, 'action': { 'name': action.name, 'implementation_url': Whatever.endswith(action_url), 'arguments_schema': action.arguments_schema, }, 'arguments': { 'foo': 'bar', } }
def canonical_json(self): from normandy.recipes.api.serializers import RecipeSerializer # Avoid circular import data = RecipeSerializer(self).data return CanonicalJSONRenderer().render(data)
def test_it_uses_cdn_url(self, rf, settings): settings.CDN_URL = 'https://example.com/cdn/' recipe = RecipeFactory() serializer = RecipeSerializer(recipe, context={'request': rf.get('/')}) assert serializer.data['action']['implementation_url'].startswith( settings.CDN_URL)
class BundleSerializer(serializers.Serializer): recipes = RecipeSerializer(many=True) country = serializers.CharField()
def disable(self, request, pk=None): recipe = self.get_object() recipe.enabled = False recipe.save() return Response(RecipeSerializer(recipe).data)