Move region exclusion to C&P (bug 821058)
This commit is contained in:
Родитель
55b614e915
Коммит
4579884416
|
@ -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> ·
|
||||
<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 & 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> ·
|
||||
<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):
|
||||
|
|
Загрузка…
Ссылка в новой задаче