Move region exclusion to C&P (bug 821058)

This commit is contained in:
Matt Basta 2012-12-28 16:07:35 -05:00
Родитель 55b614e915
Коммит 4579884416
10 изменённых файлов: 302 добавлений и 299 удалений

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

@ -1,8 +1,7 @@
(function() {
var $this;
$('.devhub-form').on('click', '.toggles a', _pd(function() {
$this = $(this);
var $choices = $this.closest('td').find('.checkbox-choices input[type=checkbox]:not(:disabled)');
$('form').on('click', '.toggles a', _pd(function() {
var $this = $(this);
var $choices = $this.closest('td, div').find('.checkbox-choices input[type=checkbox]:not(:disabled)');
if ($this.hasClass('all')) {
$choices.attr('checked', true);
} else {
@ -12,7 +11,7 @@
// Disable individual checkbox fields when we see them.
// (Customizing Django's CheckboxSelectMultiple widget is stupid.)
$('.checkbox-choices[data-disabled]').each(function() {
$this = $(this);
var $this = $(this);
var choices = JSON.parse($this.attr('data-disabled'));
var selectors = _.map(choices, function(val) {
return format('input[value="{0}"]', val);

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

@ -54,54 +54,6 @@
{% endif %}
</td>
</tr>
<tr>
<th>
{{ tip(_('Regions'),
_('Indicate regional support for your app.')) }}
{{ req_if_edit }}
</th>
<td id="regions">
{% if editable %}
{{ region_form.non_field_errors() }}
{{ region_form.regions.label }}
<p class="toggles">
<a href="#" class="all">{{ _('Select All') }}</a> &middot;
<a href="#" class="none">{{ _('None') }}</a>
</p>
{{ region_form.regions.errors }}
<div class="checkbox-choices"
data-disabled="{{ region_form.disabled_regions|json }}">
{{ region_form.regions }}
</div>
{% if region_form.disabled_regions %}
<p class="note disabled-regions">
<a href="https://developer.mozilla.org/en-US/docs/Apps/Marketplace_Review" target="_blank">
{{ _('Learn why some regions are restricted.') }}</a>
</p>
{% endif %}
<div class="other-regions">
{{ region_form.other_regions }}
{{ region_form.other_regions.label_tag() }}
{{ region_form.other_regions.errors }}
<div class="hint note">
{% trans %}
Your app will be displayed in the worldwide Marketplace and
in any regional marketplace that is added in the future.
You will receive an email notification when a new region
is added.
{% endtrans %}
</div>
</div>
{% else %}
{% set regions = addon.get_regions() %}
{% call empty_unless(regions) %}
{% for region in regions -%}
{{ region.name }}{% if not loop.last %}, {% endif %}
{% endfor %}
{% endcall %}
{% endif %}
</td>
</tr>
<tr>
<th>
<label data-for="homepage">

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

@ -5,14 +5,15 @@
{% if not waffle.switch('disabled-payments') or addon.is_premium() %}
{% do urls.append((addon.get_dev_url('payments'),
_('Compatibility & Payments'))) %}
{% endif %}
{% if not waffle.switch('disabled-payments') %}
{% if addon.is_webapp() and addon.premium_type in amo.ADDON_INAPPS
and waffle.switch('in-app-payments') %}
{% do urls.insert(4,
(addon.get_dev_url('in_app_config'), _('Manage In-App Payments'))
) %}
{% endif %}
{% else %}
{% do urls.append((addon.get_dev_url('payments'),
_('Manage Compatibility'))) %}
{% endif %}
{% if addon.is_packaged %}
{% do urls.append((addon.get_dev_url('versions'), _('Manage Status &amp; Versions'))) %}

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

@ -26,15 +26,14 @@
{#{{ l10n_menu(addon.default_locale) }}#}
<h1>{{ title }}</h1>
</header>
{{ disabled_payments_notice() }}
<section class="primary payments devhub-form" role="main">
<form action="{{ addon.get_dev_url('payments') }}" method="post">
{{ csrf() }}
<input type="hidden" name="toggle-paid" value="" />
<section id="submit-payment-type" class="island tabbable hasappendix">
<section id="submit-payment-type" class="island hasappendix {{ 'tabbable ' if payments_enabled or is_paid }}">
<div class="free tab {{ 'active' if not is_paid }}">
{% if waffle.switch('allow-b2g-paid-submission') %}
{% if payments_enabled or is_paid %}
<h2 id="free-tab-header"><a href="#">{{ _('Free') }}</a></h2>
{% else %}
<h2>{{ _('App Compatibility') }}</h2>
@ -51,31 +50,34 @@
{% endif %}
</div>
<div class="paid tab {{ 'active' if is_paid }}">
<h2 id="paid-tab-header">
{%- if no_paid -%}
<a href="#" class="tooltip disabled"
title="{{ _('Paid mode requires that your app only supports Firefox OS.') }}">
{{- _('Paid/In-app') -}}
</a>
{%- else -%}
<a href="#">{{ _('Paid/In-app') }}</a>
{%- endif -%}
</h2>
<div class="error">{{ form.errors.paid }}</div>
{%- for item in form.fields['paid_platforms'].choices -%}
{{ button(form, item) }}
{%- endfor %}
{% if not is_paid %}
<div id="paid-tab-save" class="update-payment-type">
<button data-type="paid">{{ _('Change to Paid') }}</button>
{{ _('Changing to Paid will put your app back into review.') }}
</div>
{% endif %}
</div>
{% if payments_enabled or is_paid %}
<div class="paid tab {{ 'active' if is_paid }}">
<h2 id="paid-tab-header">
{%- if no_paid -%}
<a href="#" class="tooltip disabled"
title="{{ _('Paid mode requires that your app only supports Firefox OS.') }}">
{{- _('Paid/In-app') -}}
</a>
{%- else -%}
<a href="#">{{ _('Paid/In-app') }}</a>
{%- endif -%}
</h2>
<div class="error">{{ form.errors.paid }}</div>
{%- for item in form.fields['paid_platforms'].choices -%}
{{ button(form, item) }}
{%- endfor %}
{% if not is_paid %}
<div id="paid-tab-save" class="update-payment-type">
<button data-type="paid">{{ _('Change to Paid') }}</button>
{{ _('Changing to Paid will put your app back into review.') }}
</div>
{% endif %}
</div>
{% endif %}
</section>
{% if is_paid %}
{{ disabled_payments_notice() }}
{% if is_incomplete %}
<div class="island warning">
{% trans %}
@ -108,6 +110,40 @@
{% endwith %}
</section>
{% endif %}
<section id="regions" class="island">
{{ region_form.non_field_errors() }}
{{ region_form.regions.label }}
<p class="toggles">
<a href="#" class="all">{{ _('Select All') }}</a> &middot;
<a href="#" class="none">{{ _('None') }}</a>
</p>
{{ region_form.regions.errors }}
<div class="checkbox-choices"
data-disabled="{{ region_form.disabled_regions|json }}">
{{ region_form.regions }}
</div>
{% if region_form.disabled_regions %}
<p class="note disabled-regions">
<a href="https://developer.mozilla.org/en-US/docs/Apps/Marketplace_Review" target="_blank">
{{ _('Learn why some regions are restricted.') }}</a>
</p>
{% endif %}
<div class="other-regions">
{{ region_form.other_regions }}
{{ region_form.other_regions.label_tag() }}
{{ region_form.other_regions.errors }}
<div class="hint note">
{% trans %}
Your app will be displayed in the worldwide Marketplace and
in any regional marketplace that is added in the future.
You will receive an email notification when a new region
is added.
{% endtrans %}
</div>
</div>
<button>{{ _('Save Changes') }}</button>
</section>
</form>
</section>
{% include 'developers/includes/addons_edit_nav.html' %}

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

@ -13,13 +13,14 @@ from test_utils import RequestFactory
import amo
import amo.tests
from amo.tests.test_helpers import get_image_path
from addons.models import Addon
from addons.models import Addon, AddonCategory, Category
from files.helpers import copyfileobj
import mkt
from mkt.developers import forms
from mkt.site.fixtures import fixture
from mkt.webapps.models import AddonExcludedRegion, Webapp
from mkt.webapps.models import (AddonExcludedRegion as AER, ContentRating,
Webapp)
class TestPreviewForm(amo.tests.TestCase):
@ -84,7 +85,7 @@ class TestRegionForm(amo.tests.WebappTestCase):
eq_(form.initial['other_regions'], True)
def test_initial_excluded_in_region(self):
AddonExcludedRegion.objects.create(addon=self.app,
AER.objects.create(addon=self.app,
region=mkt.regions.BR.id)
regions = list(mkt.regions.REGION_IDS)
@ -98,7 +99,7 @@ class TestRegionForm(amo.tests.WebappTestCase):
def test_initial_excluded_in_regions_and_future_regions(self):
for region in [mkt.regions.BR, mkt.regions.UK, mkt.regions.WORLDWIDE]:
AddonExcludedRegion.objects.create(addon=self.app,
AER.objects.create(addon=self.app,
region=region.id)
regions = list(mkt.regions.REGION_IDS)
@ -124,6 +125,104 @@ class TestRegionForm(amo.tests.WebappTestCase):
{'__all__': ['You must select at least one region or '
'"Other and new regions."']})
def test_exclude_each_region(self):
"""Test that it's possible to exclude each region."""
for region_id in mkt.regions.REGION_IDS:
if region_id == mkt.regions.WORLDWIDE.id:
continue
to_exclude = list(mkt.regions.REGION_IDS)
to_exclude.remove(region_id)
form = forms.RegionForm(
data={'regions': to_exclude,
'other_regions': True}, **self.kwargs)
assert form.is_valid(), form.errors
form.save()
eq_(self.app.get_region_ids(False), to_exclude)
def test_brazil_games_excluded(self):
games = Category.objects.create(type=amo.ADDON_WEBAPP, slug='games')
AddonCategory.objects.create(addon=self.app, category=games)
form = forms.RegionForm(data={'regions': mkt.regions.REGION_IDS,
'other_regions': True}, **self.kwargs)
# Developers should still be able to save form OK, even
# if they pass a bad region. Think of the grandfathered developers.
assert form.is_valid()
form.save()
# No matter what the developer tells us, still exclude Brazilian
# games.
form = forms.RegionForm(data=None, **self.kwargs)
eq_(set(form.initial['regions']),
set(mkt.regions.REGION_IDS) -
set([mkt.regions.BR.id, mkt.regions.WORLDWIDE.id]))
eq_(form.initial['other_regions'], True)
def test_brazil_games_already_excluded(self):
AER.objects.create(addon=self.app, region=mkt.regions.BR.id)
games = Category.objects.create(type=amo.ADDON_WEBAPP, slug='games')
AddonCategory.objects.create(addon=self.app, category=games)
form = forms.RegionForm(data={'regions': mkt.regions.REGION_IDS,
'other_regions': True}, **self.kwargs)
assert form.is_valid()
form.save()
form = forms.RegionForm(data=None, **self.kwargs)
eq_(set(form.initial['regions']),
set(mkt.regions.REGION_IDS) -
set([mkt.regions.BR.id, mkt.regions.WORLDWIDE.id]))
eq_(form.initial['other_regions'], True)
def test_brazil_games_with_content_rating(self):
# This game has a government content rating!
rb = mkt.regions.BR.ratingsbodies[0]
ContentRating.objects.create(
addon=self.app, ratings_body=rb.id, rating=rb.ratings[0].id)
games = Category.objects.create(type=amo.ADDON_WEBAPP, slug='games')
AddonCategory.objects.create(addon=self.app, category=games)
form = forms.RegionForm(data={'regions': mkt.regions.REGION_IDS,
'other_regions': 'on'}, **self.kwargs)
eq_(form.is_valid(), True)
form.save()
eq_(self.app.get_region_ids(True), mkt.regions.ALL_REGION_IDS)
def test_exclude_worldwide(self):
form = forms.RegionForm(data={'regions': mkt.regions.REGION_IDS,
'other_regions': False}, **self.kwargs)
eq_(form.is_valid(), True)
form.save()
eq_(self.app.get_region_ids(True), mkt.regions.REGION_IDS)
def test_reinclude_region(self):
AER.objects.create(addon=self.app, region=mkt.regions.BR.id)
form = forms.RegionForm(data={'regions': mkt.regions.REGION_IDS,
'other_regions': True}, **self.kwargs)
eq_(form.is_valid(), True)
form.save()
eq_(self.app.get_region_ids(True), mkt.regions.ALL_REGION_IDS)
def test_reinclude_worldwide(self):
AER.objects.create(addon=self.app, region=mkt.regions.WORLDWIDE.id)
form = forms.RegionForm(data={'regions': mkt.regions.REGION_IDS,
'other_regions': True}, **self.kwargs)
eq_(form.is_valid(), True)
form.save()
eq_(self.app.get_region_ids(True), mkt.regions.ALL_REGION_IDS)
class TestNewManifestForm(amo.tests.TestCase):
@mock.patch('mkt.developers.forms.verify_app_domain')

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

@ -11,10 +11,10 @@ from django.core import mail
from django.core.files.storage import default_storage as storage
from django.core.files.uploadedfile import SimpleUploadedFile
from nose import SkipTest
import mock
import waffle
from dateutil.parser import parse as parse_dt
from nose import SkipTest
from nose.plugins.attrib import attr
from nose.tools import eq_
from pyquery import PyQuery as pq
@ -32,15 +32,17 @@ from devhub.models import UserLog
from files.models import FileUpload
from files.tests.test_models import UploadTest as BaseUploadTest
from market.models import AddonPremium, Price, Refund
from stats.models import Contribution
from translations.models import Translation
from users.models import UserProfile
from versions.models import Version
import mkt
from mkt.constants import MAX_PACKAGED_APP_SIZE
from mkt.developers import tasks
from mkt.developers.models import ActivityLog
from mkt.submit.models import AppSubmissionChecklist
from mkt.webapps.models import Webapp
from stats.models import Contribution
from translations.models import Translation
from users.models import UserProfile
from versions.models import Version
class AppHubTest(amo.tests.TestCase):
@ -374,6 +376,8 @@ class TestMarketplace(MarketplaceMixin, amo.tests.TestCase):
data = {
'price': self.price.pk,
'upsell_of': self.other_addon.pk,
'regions': mkt.regions.REGION_IDS,
'other_regions': True,
}
data.update(kw)
return data

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

@ -356,33 +356,6 @@ class TestEditBasic(TestEdit):
eq_(r.context['cat_form'].errors['categories'],
['You can have only 2 categories.'])
def test_exclude_games_in_brazil(self):
games = Category.objects.create(type=amo.ADDON_WEBAPP, slug='games')
r = self.client.post(self.edit_url,
self.get_dict(categories=[games.id]))
self.assertNoFormErrors(r)
eq_(list(AER.objects.values_list('region', flat=True)),
[mkt.regions.BR.id])
def test_games_already_excluded_in_brazil(self):
AER.objects.create(addon=self.webapp, region=mkt.regions.BR.id)
games = Category.objects.create(type=amo.ADDON_WEBAPP, slug='games')
r = self.client.post(self.edit_url,
self.get_dict(categories=[games.id]))
self.assertNoFormErrors(r)
eq_(list(AER.objects.values_list('region', flat=True)),
[mkt.regions.BR.id])
def test_edit_other_categories_are_not_excluded(self):
# Keep the category around for good measure.
Category.objects.create(type=amo.ADDON_WEBAPP, slug='games')
r = self.client.post(self.url, self.get_dict())
self.assertNoFormErrors(r)
eq_(AER.objects.count(), 0)
def test_devices_listed(self):
r = self.client.post(self.url, self.get_dict())
eq_(pq(r.content)('#addon-device-types-edit').text(),
@ -1011,15 +984,10 @@ class TestEditDetails(TestEdit):
default_locale='en-US',
homepage='http://twitter.com/fligtarsmom',
privacy_policy="fligtar's mom does <em>not</em> share "
"your data with third parties.",
regions=[mkt.regions.CA.id])
"your data with third parties.")
data.update(kw)
return data
def get_excluded_ids(self):
return sorted(AER.objects.filter(addon=self.webapp)
.values_list('region', flat=True))
def test_form_url(self):
self.check_form_url('details')
@ -1120,161 +1088,16 @@ class TestEditDetails(TestEdit):
self.get_dict(homepage='xxx'))
self.assertFormError(r, 'form', 'homepage', 'Enter a valid URL.')
def test_regions_listed(self):
r = self.client.get(self.url)
eq_(strip_whitespace(pq(r.content)('#regions').text()),
', '.join(sorted(unicode(name) for id_, name in
mkt.regions.REGIONS_CHOICES_NAME)))
def test_excluded_regions_not_listed(self):
AER.objects.create(addon=self.webapp, region=mkt.regions.BR.id)
# This looks at the included regions and prints out the names
# so we can compare it to what's shown under "Regions".
expected = sorted(unicode(name) for id_, name in
mkt.regions.REGIONS_CHOICES_NAME
if id_ != mkt.regions.BR.id)
r = self.client.get(self.url)
eq_(strip_whitespace(pq(r.content)('#regions').text()),
', '.join(expected))
def test_excluded_all_regions_not_listed(self):
for region in mkt.regions.ALL_REGION_IDS:
AER.objects.create(addon=self.webapp, region=region)
r = self.client.get(self.url)
eq_(pq(r.content)('#regions .empty').length, 1)
def test_exclude_region(self):
regions = list(mkt.regions.REGION_IDS)
for region_id in regions:
to_exclude = list(regions)
to_exclude.remove(region_id)
data = self.get_dict(regions=to_exclude, other_regions=True)
r = self.client.post(self.edit_url, data)
self.assertNoFormErrors(r)
eq_(self.get_excluded_ids(), [region_id])
def test_exclude_future_regions(self):
data = self.get_dict(regions=mkt.regions.REGION_IDS,
other_regions=False)
r = self.client.post(self.edit_url, data)
self.assertNoFormErrors(r)
eq_(self.get_excluded_ids(), [mkt.regions.WORLDWIDE.id])
def test_include_regions(self):
AER.objects.create(addon=self.webapp, region=mkt.regions.BR.id)
data = self.get_dict(regions=mkt.regions.REGION_IDS,
other_regions=True)
r = self.client.post(self.edit_url, data)
self.assertNoFormErrors(r)
eq_(self.get_excluded_ids(), [])
def test_include_future_regions(self):
AER.objects.create(addon=self.webapp, region=mkt.regions.WORLDWIDE.id)
data = self.get_dict(regions=mkt.regions.REGION_IDS,
other_regions=True)
r = self.client.post(self.edit_url, data)
self.assertNoFormErrors(r)
eq_(self.get_excluded_ids(), [])
def test_include_all_and_future_regions(self):
AER.objects.create(addon=self.webapp, region=mkt.regions.WORLDWIDE.id)
data = self.get_dict(regions=mkt.regions.REGION_IDS,
other_regions=True)
r = self.client.post(self.edit_url, data)
self.assertNoFormErrors(r)
eq_(self.get_excluded_ids(), [])
def test_brazil_games_excluded(self):
games = Category.objects.create(type=amo.ADDON_WEBAPP, slug='games')
AddonCategory.objects.create(addon=self.webapp, category=games)
r = self.client.post(self.edit_url,
self.get_dict(regions=mkt.regions.REGION_IDS,
other_regions=True))
# Developers should still be able to save form OK, even
# if they pass a bad region. Think of the grandfathered developers.
self.assertNoFormErrors(r)
# No matter what the developer tells us, still exclude Brazilian
# games.
eq_(self.get_excluded_ids(), [mkt.regions.BR.id])
def test_brazil_games_already_excluded(self):
def test_games_already_excluded_in_brazil(self):
AER.objects.create(addon=self.webapp, region=mkt.regions.BR.id)
games = Category.objects.create(type=amo.ADDON_WEBAPP, slug='games')
AddonCategory.objects.create(addon=self.webapp, category=games)
r = self.client.post(self.edit_url,
self.get_dict(regions=mkt.regions.REGION_IDS,
other_regions=True))
r = self.client.post(
self.edit_url, self.get_dict(categories=[games.id]))
self.assertNoFormErrors(r)
eq_(self.get_excluded_ids(), [mkt.regions.BR.id])
def test_brazil_games_with_content_rating(self):
# This game has a government content rating!
rb = mkt.regions.BR.ratingsbodies[0]
ContentRating.objects.create(addon=self.webapp,
ratings_body=rb.id, rating=rb.ratings[0].id)
games = Category.objects.create(type=amo.ADDON_WEBAPP, slug='games')
AddonCategory.objects.create(addon=self.webapp, category=games)
r = self.client.post(self.edit_url,
self.get_dict(regions=mkt.regions.REGION_IDS,
other_regions=True))
self.assertNoFormErrors(r)
eq_(self.get_excluded_ids(), [])
def test_brazil_games_form_disabled(self):
games = Category.objects.create(type=amo.ADDON_WEBAPP, slug='games')
AddonCategory.objects.create(addon=self.webapp, category=games)
r = self.client.get(self.edit_url, self.get_dict())
self.assertNoFormErrors(r)
td = pq(r.content)('#regions')
eq_(td.find('div[data-disabled]').attr('data-disabled'),
json.dumps([mkt.regions.BR.id]))
eq_(td.find('.note.disabled-regions').length, 1)
def test_brazil_games_form_enabled_with_content_rating(self):
rb = mkt.regions.BR.ratingsbodies[0]
ContentRating.objects.create(addon=self.webapp,
ratings_body=rb.id, rating=rb.ratings[0].id)
games = Category.objects.create(type=amo.ADDON_WEBAPP, slug='games')
AddonCategory.objects.create(addon=self.webapp, category=games)
r = self.client.get(self.edit_url, self.get_dict())
self.assertNoFormErrors(r)
td = pq(r.content)('#regions')
eq_(td.find('div[data-disabled]').attr('data-disabled'),
json.dumps([]))
eq_(td.find('.note.disabled-regions').length, 0)
def test_brazil_other_cats_form_enabled(self):
r = self.client.get(self.edit_url, self.get_dict())
self.assertNoFormErrors(r)
td = pq(r.content)('#regions')
eq_(td.find('div[data-disabled]').attr('data-disabled'),
json.dumps([]))
eq_(td.find('.note.disabled-regions').length, 0)
eq_(list(AER.objects.filter(addon=self.webapp)
.values_list('region', flat=True)),
[mkt.regions.BR.id])
class TestEditSupport(TestEdit):

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

@ -9,12 +9,14 @@ from pyquery import PyQuery as pq
import amo
import amo.tests
from addons.models import Addon
from addons.models import Addon, AddonCategory, Category
from market.models import Price
from users.models import UserProfile
import mkt
from mkt.developers.models import PaymentAccount, SolitudeSeller
from mkt.inapp_pay.models import InappConfig
from mkt.webapps.models import AddonExcludedRegion as AER, ContentRating
def create_inapp_config(public_key='pub-key', private_key='priv-key',
@ -247,23 +249,36 @@ class TestPayments(amo.tests.TestCase):
def get_webapp(self):
return Addon.objects.get(pk=337141)
def get_region_list(self):
return list(AER.objects.values_list('region', flat=True))
def get_postdata(self, base):
extension = {'regions': self.get_region_list(),
'other_regions': 'on'}
base.update(extension)
return base
def test_free(self):
res = self.client.post(self.url, {'toggle-paid': 'free'})
res = self.client.post(
self.url, self.get_postdata({'toggle-paid': 'free'}))
self.assert3xx(res, self.url)
eq_(self.get_webapp().premium_type, amo.ADDON_FREE)
def test_premium_passes(self):
self.webapp.update(premium_type=amo.ADDON_FREE)
res = self.client.post(self.url, {'toggle-paid': 'paid'})
res = self.client.post(
self.url, self.get_postdata({'toggle-paid': 'paid'}))
self.assert3xx(res, self.url)
eq_(self.get_webapp().premium_type, amo.ADDON_PREMIUM)
def test_premium_in_app_passes(self):
self.webapp.update(premium_type=amo.ADDON_FREE)
res = self.client.post(self.url, {'toggle-paid': 'paid'})
res = self.client.post(
self.url, self.get_postdata({'toggle-paid': 'paid'}))
self.assert3xx(res, self.url)
res = self.client.post(self.url, {'allow_inapp': True,
'price': self.price.pk})
res = self.client.post(
self.url, self.get_postdata({'allow_inapp': True,
'price': self.price.pk}))
self.assert3xx(res, self.url)
eq_(self.get_webapp().premium_type, amo.ADDON_PREMIUM_INAPP)
@ -271,8 +286,9 @@ class TestPayments(amo.tests.TestCase):
self.webapp.update(premium_type=amo.ADDON_PREMIUM,
status=amo.STATUS_NULL,
highest_status=amo.STATUS_PENDING)
res = self.client.post(self.url, {'toggle-paid': 'free',
'price': self.price.pk})
res = self.client.post(
self.url, self.get_postdata({'toggle-paid': 'free',
'price': self.price.pk}))
self.assert3xx(res, self.url)
eq_(self.get_webapp().status, amo.STATUS_PENDING)
@ -287,7 +303,8 @@ class TestPayments(amo.tests.TestCase):
Price.objects.create(price='10.00') # Make one more tier.
self.webapp.update(premium_type=amo.ADDON_FREE)
res = self.client.post(self.url, {'toggle-paid': 'paid'}, follow=True)
res = self.client.post(
self.url, self.get_postdata({'toggle-paid': 'paid'}), follow=True)
pqr = pq(res.content)
eq_(pqr('select[name=price] option[selected]').attr('value'),
str(Price.objects.get(price='0.99').id))
@ -310,9 +327,78 @@ class TestPayments(amo.tests.TestCase):
solitude_seller=seller, bango_package_id=123)
# Associate account with app.
res = self.client.post(self.url, {'toggle-paid': 'paid',
'price': self.price.pk,
'accounts': acct.pk}, follow=True)
res = self.client.post(
self.url, self.get_postdata({'toggle-paid': 'paid',
'price': self.price.pk,
'accounts': acct.pk}), follow=True)
self.assertNoFormErrors(res)
eq_(res.status_code, 200)
eq_(self.webapp.app_payment_account.payment_account.pk, acct.pk)
class TestRegions(amo.tests.TestCase):
fixtures = ['base/apps', 'base/users', 'webapps/337141-steamcube']
def setUp(self):
self.webapp = self.get_webapp()
self.url = self.webapp.get_dev_url('payments')
self.username = 'admin@mozilla.com'
assert self.client.login(username=self.username, password='password')
self.patch = mock.patch('mkt.developers.models.client')
self.sol = self.patch.start()
def tearDown(self):
self.patch.stop()
def get_webapp(self):
return Addon.objects.get(pk=337141)
def get_dict(self, **kwargs):
extension = {'regions': mkt.regions.REGION_IDS,
'other_regions': 'on'}
extension.update(kwargs)
return extension
def get_excluded_ids(self):
return sorted(AER.objects.filter(addon=self.webapp)
.values_list('region', flat=True))
def test_edit_other_categories_are_not_excluded(self):
# Keep the category around for good measure.
Category.objects.create(type=amo.ADDON_WEBAPP, slug='games')
r = self.client.post(self.url, self.get_dict())
self.assertNoFormErrors(r)
eq_(AER.objects.count(), 0)
def test_brazil_games_form_disabled(self):
games = Category.objects.create(type=amo.ADDON_WEBAPP, slug='games')
AddonCategory.objects.create(addon=self.webapp, category=games)
r = self.client.get(self.url, self.get_dict())
self.assertNoFormErrors(r)
td = pq(r.content)('#regions')
eq_(td.find('div[data-disabled]').attr('data-disabled'),
'[%d]' % mkt.regions.BR.id)
eq_(td.find('.note.disabled-regions').length, 1)
def test_brazil_games_form_enabled_with_content_rating(self):
rb = mkt.regions.BR.ratingsbodies[0]
ContentRating.objects.create(
addon=self.webapp, ratings_body=rb.id, rating=rb.ratings[0].id)
games = Category.objects.create(type=amo.ADDON_WEBAPP, slug='games')
AddonCategory.objects.create(addon=self.webapp, category=games)
r = self.client.get(self.url)
td = pq(r.content)('#regions')
eq_(td.find('div[data-disabled]').attr('data-disabled'), '[]')
eq_(td.find('.note.disabled-regions').length, 0)
def test_brazil_other_cats_form_enabled(self):
r = self.client.get(self.url)
td = pq(r.content)('#regions')
eq_(td.find('div[data-disabled]').attr('data-disabled'), '[]')
eq_(td.find('.note.disabled-regions').length, 0)

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

@ -51,8 +51,7 @@ from mkt.developers.forms import (AppFormBasic, AppFormDetails, AppFormMedia,
AppFormSupport, AppFormTechnical,
CategoryForm, ImageAssetFormSet,
InappConfigForm, NewPackagedAppForm,
PreviewFormSet, RegionForm,
trap_duplicate)
PreviewFormSet, trap_duplicate)
from mkt.developers.utils import check_upload
from mkt.inapp_pay.models import InappConfig
from mkt.submit.forms import NewWebappVersionForm
@ -649,7 +648,7 @@ def addons_section(request, addon_id, addon, section, editable=False,
raise http.Http404()
tags = image_assets = previews = restricted_tags = []
cat_form = device_type_form = region_form = None
cat_form = device_type_form = None
if section == 'basic':
tags = addon.tags.not_blacklisted().values_list('tag_text', flat=True)
@ -665,9 +664,6 @@ def addons_section(request, addon_id, addon, section, editable=False,
request.POST or None, prefix='files',
queryset=addon.get_previews())
elif section == 'details':
region_form = RegionForm(request.POST or None, product=addon)
elif (section == 'admin' and
not acl.action_allowed(request, 'Apps', 'Configure') and
not acl.action_allowed(request, 'Apps', 'ViewConfiguration')):
@ -686,12 +682,8 @@ def addons_section(request, addon_id, addon, section, editable=False,
instance=addon, request=request)
if (form.is_valid()
and (not previews or previews.is_valid())
and (not region_form or region_form.is_valid())
and (not image_assets or image_assets.is_valid())):
if region_form:
region_form.save()
addon = form.save(addon)
if 'manifest_url' in form.changed_data:
@ -741,8 +733,7 @@ def addons_section(request, addon_id, addon, section, editable=False,
'preview_form': previews,
'image_asset_form': image_assets,
'valid_slug': valid_slug,
'device_type_form': device_type_form,
'region_form': region_form}
'device_type_form': device_type_form}
return jingo.render(request,
'developers/apps/edit/%s.html' % section, data)

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

@ -3,6 +3,7 @@ from django.shortcuts import get_object_or_404, redirect
import commonware
import jingo
import waffle
from tower import ugettext as _
import amo
@ -33,6 +34,9 @@ def payments(request, addon_id, addon, webapp=False):
request.POST or None, request=request, addon=addon,
user=request.amo_user)
region_form = forms.RegionForm(
request.POST or None, product=addon)
upsell_form = forms.UpsellForm(
request.POST or None, addon=addon, user=request.amo_user)
@ -42,9 +46,12 @@ def payments(request, addon_id, addon, webapp=False):
if request.method == 'POST':
success = all(form.is_valid() for form in
[premium_form, upsell_form, bango_account_list_form])
[premium_form, region_form, upsell_form,
bango_account_list_form])
if success:
region_form.save()
toggling = premium_form.is_toggling()
try:
@ -102,13 +109,18 @@ def payments(request, addon_id, addon, webapp=False):
request, 'developers/payments/premium.html',
{'addon': addon, 'webapp': webapp, 'premium': addon.premium,
'form': premium_form, 'upsell_form': upsell_form,
'region_form': region_form,
'DEVICE_LOOKUP': DEVICE_LOOKUP,
'is_paid': addon.premium_type in amo.ADDON_PREMIUMS,
'no_paid': cannot_be_paid,
'is_incomplete': addon.status == amo.STATUS_NULL,
# Bango values
'bango_account_form': forms.BangoPaymentAccountForm(),
'bango_account_list_form': bango_account_list_form, })
'bango_account_list_form': bango_account_list_form,
# Waffles
'payments_enabled':
waffle.switch_is_active('allow-b2g-paid-submission') and
not waffle.switch_is_active('disabled-payments')})
def payments_accounts(request):