ignore version info for non-selected apps - add-on packager

This commit is contained in:
Chris Van 2011-10-01 22:18:12 -07:00
Родитель 4f119a1b46
Коммит 4f688a52c3
4 изменённых файлов: 91 добавлений и 78 удалений

Просмотреть файл

@ -8,11 +8,13 @@ import time
from django import forms
from django.conf import settings
from django.forms.fields import Field
from django.test.client import Client
from django.utils import translation
import elasticutils
import nose
from nose.tools import eq_
import test_utils
from redisutils import mock_redis, reset_redis
@ -61,6 +63,10 @@ def initial(form):
return data
def assert_required(error_msg):
eq_(error_msg, unicode(Field.default_error_messages['required']))
class RedisTest(object):
"""Mixin for when you need to mock redis for testing."""

Просмотреть файл

@ -22,6 +22,7 @@ from django.core.serializers import json
from django.core.validators import ValidationError, validate_slug
from django.core.mail import send_mail as django_send_mail
from django.db.models.sql.datastructures import EmptyResultSet
from django.forms.fields import Field
from django.template import Context, loader
from django.utils.translation import trans_real
from django.utils.functional import Promise
@ -293,6 +294,10 @@ def slug_validator(s, ok=SLUG_OK, lower=True):
code=validate_slug.code)
def raise_required():
raise ValidationError(Field.default_error_messages['required'])
def clear_messages(request):
"""
Clear any messages out of the messages framework for the authenticated

Просмотреть файл

@ -5,6 +5,7 @@ import socket
from django import forms
from django.conf import settings
from django.db.models import Q
from django.forms.fields import Field
from django.forms.models import modelformset_factory
from django.forms.formsets import formset_factory, BaseFormSet
from django.utils.safestring import mark_safe
@ -21,7 +22,7 @@ from addons.models import (Addon, AddonDependency, AddonUpsell, AddonUser,
BlacklistedSlug, Charity, Preview)
from amo.forms import AMOModelForm
from amo.urlresolvers import reverse
from amo.utils import slug_validator
from amo.utils import raise_required, slug_validator
from amo.widgets import EmailWidget
from applications.models import Application, AppVersion
@ -763,10 +764,10 @@ class PackagerBasicForm(forms.Form):
class PackagerCompatForm(forms.Form):
enabled = forms.BooleanField(required=False)
min_ver = forms.ModelChoiceField(AppVersion.objects.none(),
empty_label=None,
empty_label=None, required=False,
label=_lazy(u'Minimum'))
max_ver = forms.ModelChoiceField(AppVersion.objects.none(),
empty_label=None,
empty_label=None, required=False,
label=_lazy(u'Maximum'))
def __init__(self, *args, **kwargs):
@ -784,33 +785,43 @@ class PackagerCompatForm(forms.Form):
self.fields['min_ver'].queryset = qs.filter(~Q(version__contains='*'))
self.fields['max_ver'].queryset = qs.all()
def clean_min_ver(self):
if self.cleaned_data['enabled'] and not self.cleaned_data['min_ver']:
raise_required()
return self.cleaned_data['min_ver']
def clean_max_ver(self):
if self.cleaned_data['enabled'] and not self.cleaned_data['max_ver']:
raise_required()
return self.cleaned_data['max_ver']
def clean(self):
if self.errors:
return
data = self.cleaned_data
if not data['enabled']:
return data
min_ver = data['min_ver']
max_ver = data['max_ver']
if not (min_ver and max_ver):
raise forms.ValidationError(
_('Invalid version range.'))
if data['enabled']:
min_ver = data['min_ver']
max_ver = data['max_ver']
if not (min_ver and max_ver):
raise forms.ValidationError(_('Invalid version range.'))
if min_ver.version_int > max_ver.version_int:
raise forms.ValidationError(
if min_ver.version_int > max_ver.version_int:
raise forms.ValidationError(
_('Min version must be less than Max version.'))
# Pass back the app name and GUID.
data['min_ver'] = str(min_ver)
data['max_ver'] = str(max_ver)
data['name'] = self.app.pretty
data['guid'] = self.app.guid
# Pass back the app name and GUID.
data['min_ver'] = str(min_ver)
data['max_ver'] = str(max_ver)
data['name'] = self.app.pretty
data['guid'] = self.app.guid
return data
class PackagerCompatBaseFormSet(BaseFormSet):
def __init__(self, *args, **kw):
super(PackagerCompatBaseFormSet, self).__init__(*args, **kw)
self.initial = [{'application': a} for a in amo.APP_USAGE]
@ -819,14 +830,15 @@ class PackagerCompatBaseFormSet(BaseFormSet):
def clean(self):
if any(self.errors):
return
if not any(cf.cleaned_data.get('enabled') for cf in self.forms):
if (not self.forms or not
any(f.cleaned_data.get('enabled') for f in self.forms)):
raise forms.ValidationError(
_('At least one target application must be selected.'))
return self.cleaned_data
PackagerCompatFormSet = formset_factory(PackagerCompatForm,
formset=PackagerCompatBaseFormSet,
extra=0)
formset=PackagerCompatBaseFormSet, extra=0)
class PackagerFeaturesForm(forms.Form):
@ -958,12 +970,12 @@ class PremiumForm(happyforms.Form):
def clean_text(self):
if self.cleaned_data['do_upsell'] and not self.cleaned_data['text']:
raise forms.ValidationError(_('This field is required.'))
raise_required()
return self.cleaned_data['text']
def clean_free(self):
if self.cleaned_data['do_upsell'] and not self.cleaned_data['free']:
raise forms.ValidationError(_('This field is required.'))
raise_required()
return self.cleaned_data['free']
def save(self):

Просмотреть файл

@ -7,7 +7,7 @@ from nose.tools import eq_
from pyquery import PyQuery as pq
import amo.tests
from amo.tests import formset, initial
from amo.tests import assert_required, formset, initial
from amo.urlresolvers import reverse
from addons.models import BlacklistedSlug
from devhub.views import packager_path
@ -20,35 +20,13 @@ class TestAddOnPackager(amo.tests.TestCase):
def setUp(self):
assert self.client.login(username='regular@mozilla.com',
password='password')
self.package_addon = reverse('devhub.package_addon')
self.url = reverse('devhub.package_addon')
ctx = self.client.get(self.package_addon).context['compat_forms']
ctx = self.client.get(self.url).context['compat_forms']
self.compat_form = initial(ctx.initial_forms[1])
def test_has_versions(self):
"""Test that versions are listed in targetApplication fields."""
r = self.client.get(self.package_addon)
eq_(r.status_code, 200)
doc = pq(r.content)
# Assert that the first dropdown (Firefox) has at least thirty items.
assert len(doc('.supported-apps select').children()) > 30
def test_no_mozilla(self):
"""
Test that the Mozilla browser is not represented in the
targetApplication list.
"""
r = self.client.get(self.package_addon)
eq_(r.status_code, 200)
doc = pq(r.content)
for label in doc('.supported-apps label.app'):
assert pq(label).text() != 'Mozilla'
def _form_data(self, data=None, compat_form=True):
def _form_data(self, data={}, compat_forms=None):
"""Build the initial data set for the form."""
initial_data = {'author_name': 'author',
'contributors': '',
'description': '',
@ -56,14 +34,29 @@ class TestAddOnPackager(amo.tests.TestCase):
'package_name': 'name',
'id': 'foo@bar.com',
'version': '1.2.3'}
if compat_form:
initial_data.update(formset(self.compat_form))
if not compat_forms:
compat_forms = [self.compat_form]
initial_data.update(formset(*compat_forms))
if data:
initial_data.update(data)
return initial_data
def test_required_login(self):
self.client.logout()
r = self.client.get(self.url)
eq_(r.status_code, 302)
def test_form_initial(self):
"""Ensure that the initial forms for each application are present."""
r = self.client.get(self.url)
eq_(r.status_code, 200)
rows = pq(r.content)('.supported-apps li.row')
classes = [a.short for a in amo.APP_USAGE]
eq_(rows.length, len(classes))
for app_class, label in zip(classes, rows('label.app')):
assert pq(label).hasClass(app_class), (
'Label for application %r not found' % app_class)
def test_validate_pass(self):
"""
Test that a proper set of data will pass validation and pass through
@ -72,47 +65,43 @@ class TestAddOnPackager(amo.tests.TestCase):
self.compat_form['enabled'] = 'on'
self.compat_form['min_ver'] = '86'
self.compat_form['max_ver'] = '114'
r = self.client.post(self.package_addon, self._form_data(),
follow=True)
r = self.client.post(self.url, self._form_data(), follow=True)
eq_(r.status_code, 200)
eq_(pq(pq(r.content)('h3')[0]).text(), 'Add-on packaged successfully!')
def test_validate_name(self):
"""Test that the add-on name is properly validated."""
r = self.client.post(self.package_addon,
self._form_data({'name': 'Mozilla App'}))
r = self.client.post(self.url, self._form_data({'name': 'Mozilla <3'}))
self.assertFormError(
r, 'basic_form', 'name',
'Add-on names should not contain Mozilla trademarks.')
def test_validate_package_name_required(self):
r = self.client.post(self.package_addon,
self._form_data({'package_name': ''}))
r = self.client.post(self.url, self._form_data({'package_name': ''}))
self.assertFormError(r, 'basic_form', 'package_name',
'This field is required.')
def test_validate_package_name_format(self):
r = self.client.post(self.package_addon,
r = self.client.post(self.url,
self._form_data({'package_name': 'addon name'}))
self.assertFormError(r, 'basic_form', 'package_name',
validate_slug.message)
def test_validate_package_name_taken(self):
r = self.client.post(self.package_addon,
r = self.client.post(self.url,
self._form_data({'package_name': 'a3615'}))
self.assertFormError(r, 'basic_form', 'package_name',
'This slug is already in use.')
def test_validate_package_name_blacklisted(self):
BlacklistedSlug.objects.create(name='slap_tickle')
r = self.client.post(self.package_addon,
r = self.client.post(self.url,
self._form_data({'package_name': 'slap_tickle'}))
self.assertFormError(r, 'basic_form', 'package_name',
'The slug cannot be: slap_tickle.')
def test_validate_version(self):
"""Test that the add-on version is properly validated."""
r = self.client.post(self.package_addon,
r = self.client.post(self.url,
self._form_data({'version': 'invalid version'}))
self.assertFormError(
r, 'basic_form', 'version',
@ -120,33 +109,34 @@ class TestAddOnPackager(amo.tests.TestCase):
def test_validate_id(self):
"""Test that the add-on id is properly validated."""
r = self.client.post(self.package_addon,
self._form_data({'id': 'invalid id'}))
r = self.client.post(self.url, self._form_data({'id': 'invalid id'}))
self.assertFormError(
r, 'basic_form', 'id',
'The add-on ID must be a UUID string or an email address.')
def test_validate_version_enabled(self):
"""Test that at least one version must be enabled."""
# Nothing needs to be done; no apps are enabled by default.
r = self.client.post(self.package_addon, self._form_data())
assert not r.context['compat_forms'].is_valid()
def test_app_required(self):
"""Ensure that at least one target application is required."""
self.compat_form = {}
r = self.client.post(self.url, self._form_data())
eq_(r.context['compat_forms'].non_form_errors(),
['At least one target application must be selected.'])
def test_enabled_apps_version_required(self):
"""Min/Max Version fields should be required for enabled apps."""
forms = [self.compat_form, {'enabled': 'on'}]
r = self.client.post(self.url, self._form_data(compat_forms=forms))
assert_required(r.context['compat_forms'].errors[1]['min_ver'][0])
assert_required(r.context['compat_forms'].errors[1]['max_ver'][0])
def test_validate_version_order(self):
"""Test that the min version is lte the max version."""
self.compat_form['enabled'] = 'on'
self.compat_form['min_ver'] = '114'
self.compat_form['max_ver'] = '86'
r = self.client.post(self.package_addon,
self._form_data())
r = self.client.post(self.url, self._form_data())
eq_(r.context['compat_forms'].errors[0]['__all__'][0],
'Min version must be less than Max version.')
def test_required_login(self):
self.client.logout()
r = self.client.get(self.package_addon)
eq_(r.status_code, 302)
class TestPackagerJSON(amo.tests.TestCase):
fixtures = ['base/apps', 'base/users', 'base/appversion']