From 1e89fb6fd508ea33e5ce015023dc8edd471cffc0 Mon Sep 17 00:00:00 2001 From: Andy McKay Date: Tue, 23 Oct 2012 17:37:02 -0700 Subject: [PATCH] merge in packaged uploads, device and payment choices to submission (bug 778882) --- media/css/devreg/submit.less | 44 ++++++ media/css/devreg/tabs.less | 51 +++++++ .../img/developers/firefox_android_phone.png | Bin 0 -> 8958 bytes .../img/developers/firefox_android_tablet.png | Bin 0 -> 10345 bytes media/img/developers/firefox_logo.png | Bin 0 -> 31402 bytes media/img/developers/firefox_phone.png | Bin 0 -> 31756 bytes media/js/common/upload-packaged-app.js | 6 +- media/js/devreg/devhub.js | 1 + media/js/devreg/submit.js | 64 +++++++- media/js/devreg/tabs.js | 37 +++++ migrations/498-b2g-payments-submission.sql | 3 + mkt/asset_bundles.py | 2 + mkt/submit/forms.py | 128 +++++++++++++--- mkt/submit/templates/submit/choose.html | 73 --------- mkt/submit/templates/submit/manifest.html | 141 ++++++++++++------ mkt/submit/templates/submit/upload.html | 37 ----- mkt/submit/tests/test_forms.py | 100 +++++++++++++ mkt/submit/tests/test_views.py | 57 +++---- mkt/submit/urls.py | 2 - mkt/submit/views.py | 62 ++------ 20 files changed, 550 insertions(+), 258 deletions(-) create mode 100644 media/css/devreg/tabs.less create mode 100644 media/img/developers/firefox_android_phone.png create mode 100644 media/img/developers/firefox_android_tablet.png create mode 100644 media/img/developers/firefox_logo.png create mode 100644 media/img/developers/firefox_phone.png create mode 100644 media/js/devreg/tabs.js create mode 100644 migrations/498-b2g-payments-submission.sql delete mode 100644 mkt/submit/templates/submit/choose.html delete mode 100644 mkt/submit/templates/submit/upload.html create mode 100644 mkt/submit/tests/test_forms.py diff --git a/media/css/devreg/submit.less b/media/css/devreg/submit.less index 9d76ca8a2a..d1a591c1dc 100644 --- a/media/css/devreg/submit.less +++ b/media/css/devreg/submit.less @@ -93,3 +93,47 @@ h2 .soon { } } } + +#submit-payment-type { + .wrapper { + display: inline-block; + width: 222px; + margin-right: 10px; + &:last-child { + margin-right: 0; + width: 221px; + } + a { + text-decoration: none; + text-align: center; + padding: 180px 10px 20px; + margin-bottom: 0; + &#free-os, &#paid-os { + background: url(../../img/developers/firefox_phone.png) no-repeat center 25px; + } + &#free-desktop { + background: url(../../img/developers/firefox_logo.png) no-repeat center 25px; + } + &#free-phone { + background: url(../../img/developers/firefox_android_phone.png) no-repeat center 25px; + } + &#free-tablet { + background: url(../../img/developers/firefox_android_tablet.png) no-repeat center 40px; + } + &#free-os, &#free-desktop, &#free-phone, &#free-tablet, &#paid-os { + &.selected { + background-color: @notice-yellow; + } + } + div { + color: #484848; + } + } + } +} + +#upload-file { + &.spacer { + margin-top: 60px; + } +} diff --git a/media/css/devreg/tabs.less b/media/css/devreg/tabs.less new file mode 100644 index 0000000000..2cffd6c073 --- /dev/null +++ b/media/css/devreg/tabs.less @@ -0,0 +1,51 @@ +@import 'lib'; + +.tabbable { + position: relative; + margin-top: 52px; + .border-radius(0 0 5px 5px); + hgroup { + position: absolute; + top: -44px; + width: 100%; + left: -1px; + h2 { + .border-box(); + display: inline-block; + a { + .border-box(); + display: block; + text-align: center; + border: 1px solid #e5e2db; + .border-radius(5px 5px 0 0); + line-height: 42px; + margin-right: 10px; + background-color: #f9f9f9; + border-bottom: 0; + color: #949494; + &:hover { + text-decoration: none; + } + } + &.active a { + border: 1px solid @taupe; + border-bottom: 1px solid @white; + background-color: @white; + color: #484848; + } + &:last-child { + position: absolute; + right: -2px; + a { + margin-right: 0; + } + } + } + } + .tab { + display: none; + &.active { + display: block; + } + } +} diff --git a/media/img/developers/firefox_android_phone.png b/media/img/developers/firefox_android_phone.png new file mode 100644 index 0000000000000000000000000000000000000000..02580afe6da55394446c4d890a2055b73173a3df GIT binary patch literal 8958 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 literal 0 HcmV?d00001 diff --git a/media/img/developers/firefox_android_tablet.png b/media/img/developers/firefox_android_tablet.png new file mode 100644 index 0000000000000000000000000000000000000000..604004388a4a0d4b5e81d05e263c7dd6b3a3b7d4 GIT binary patch literal 10345 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 XFlF!0;>-TI{HGxEQMyLbIQahnt0Pxs literal 0 HcmV?d00001 diff --git a/media/img/developers/firefox_logo.png b/media/img/developers/firefox_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..091bea3b94700e480e97ed74fdb0159e8e646649 GIT binary patch literal 31402 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

w`P2RoQ2q)O4EtkMgSn~5w8 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').text(message).appendTo(upload_results); diff --git a/media/js/devreg/devhub.js b/media/js/devreg/devhub.js index b73ec49fea..34e36c0592 100644 --- a/media/js/devreg/devhub.js +++ b/media/js/devreg/devhub.js @@ -180,6 +180,7 @@ $(document).ready(function() { function check_webapp_validation(results) { var $upload_field = $('#upload-webapp-url'); $('#id_upload').val(results.upload); + $('#id_packaged').val(''); if(results.error) { $upload_field.trigger("upload_finished", [false, results, results.error]); } else if(! results.validation) { diff --git a/media/js/devreg/submit.js b/media/js/devreg/submit.js index 029f22e084..ff13bbe1aa 100644 --- a/media/js/devreg/submit.js +++ b/media/js/devreg/submit.js @@ -1,6 +1,14 @@ (function(exports) { "use strict"; + function _pd(func) { + // Prevent-default function wrapper. + return function(e) { + e.preventDefault(); + func.apply(this, arguments); + }; + } + exports.houdini = function() { // Initialize magic labels. $(document).delegate('.houdini.ready .edit', 'click', _pd(function(e) { @@ -34,9 +42,63 @@ $ctx.addClass('active'); }); }); - }) + }); + }; + + // Reset selected device buttons and values. + $('#submit-payment-type h2 a').click(function(e) { + $('#submit-payment-type a.choice').removeClass('selected'); + $('#id_free').val([]); + $('#id_paid').val([]); + }); + + + // When a big device button is clicked, update the form. + $('#submit-payment-type a.choice').on('click', + function(event) { + var $this = $(this), + $input = $('#id_' + this.id.split('-')[0]), + old = $input.val() || [], + val = $this.data('value'); + + if (old.indexOf(val) === -1) { + $this.addClass('selected'); + old.push(val); + $input.val(old); + } else { + $this.removeClass('selected'); + delete old[old.indexOf(val)]; + $input.val(old); + } + show_packaged(); + event.preventDefault(); + } + ); + + // Show packaged. + function show_packaged() { + var $target = $('#upload-file hgroup h2'); + if ($target.length < 2) { + return; + } + if ($('#id_free option[value=free-os]:selected').length || + $('#id_paid option[value=paid-os]:selected').length) { + $target.eq(1).css({'display': 'inline'}); + } else { + $target.eq(1).css({'display': 'none'}); + } } + // On page load, update the big device buttons with the values in the form. + $('#upload-webapp select').each(function(i, e) { + $.each($(e).val() || [], function() { + $('#submit-payment-type #' + this).addClass('selected'); + }); + }); + + // Hide the packaged tab, if needed. + show_packaged(); + })(typeof exports === 'undefined' ? (this.submit_details = {}) : exports); diff --git a/media/js/devreg/tabs.js b/media/js/devreg/tabs.js new file mode 100644 index 0000000000..57da09bc37 --- /dev/null +++ b/media/js/devreg/tabs.js @@ -0,0 +1,37 @@ +(function() { + // Tabbable + $('.tabbable').each(function() { + var $this = $(this); + $this.find('.active h2').addClass('active'); + + var $headers = $this.find('.tab h2').detach(), + numTabs = $headers.length; + + if (numTabs === (0 || 1)) { + return; + } + + var w = Math.floor(100 / numTabs), + $hgroup = $('

'); + + $headers.css({'width': w + '%'}); + $hgroup.append($headers); + $this.prepend($hgroup); + + $hgroup.find('a').each(function(i, e) { + $(this).on('click.switchtab', function(evt) { + var $myParent = $(evt.target).parent(); + if ($myParent.hasClass('active')) { + evt.preventDefault(); + return; + } else { + $hgroup.find('h2').removeClass('active'); + $myParent.addClass('active'); + } + $this.find('.tab').removeClass('active'); + $this.find('.tab:eq(' + i + ')').addClass('active'); + evt.preventDefault(); + }); + }); + }); +})(); diff --git a/migrations/498-b2g-payments-submission.sql b/migrations/498-b2g-payments-submission.sql new file mode 100644 index 0000000000..6e567a91b3 --- /dev/null +++ b/migrations/498-b2g-payments-submission.sql @@ -0,0 +1,3 @@ +INSERT INTO `waffle_switch_mkt` (name, active, note) + VALUES ('allow-b2g-paid-submission', 0, + 'Enable this to allow paid apps in the submission process.'); diff --git a/mkt/asset_bundles.py b/mkt/asset_bundles.py index 1f0792d66a..0e60b0222c 100644 --- a/mkt/asset_bundles.py +++ b/mkt/asset_bundles.py @@ -58,6 +58,7 @@ CSS = { 'css/devreg/submit-details.less', 'css/devreg/validation.less', 'css/devreg/submit.less', + 'css/devreg/tabs.less', 'css/impala/personas.less', 'css/impala/colorpicker.less', @@ -206,6 +207,7 @@ JS = { # New stuff. 'js/devreg/devhub.js', 'js/devreg/submit.js', + 'js/devreg/tabs.js', 'js/devreg/edit.js', 'js/impala/persona_creation.js', 'js/lib/jquery.minicolors.js', diff --git a/mkt/submit/forms.py b/mkt/submit/forms.py index 42148ce218..0a7dfa718d 100644 --- a/mkt/submit/forms.py +++ b/mkt/submit/forms.py @@ -4,6 +4,7 @@ from django import forms import happyforms from tower import ugettext as _, ugettext_lazy as _lazy +import waffle from addons.forms import AddonFormBasic from addons.models import Addon, AddonUpsell @@ -38,31 +39,125 @@ class DevAgreementForm(happyforms.Form): notification_id=app_surveys.id, update={'enabled': True}) + + + class NewWebappForm(happyforms.Form): + # The selections for free. + FREE = ( + ('free-os', _lazy('Firefox OS')), + ('free-desktop', _lazy('Firefox')), + ('free-phone', _lazy('Firefox Mobile')), + ('free-tablet', _lazy('Firefox Tablet')), + ) + + # The selections for paid. + PAID = ( + ('paid-os', _lazy('Firefox OS')), + ) + + # Extra information about those values for display in the page. + DEVICE_LOOKUP = { + 'free-os': _lazy('Fully open mobile ecosystem'), + 'free-desktop': _lazy('Windows, Mac and Linux'), + 'free-phone': _lazy('Android smartphones'), + 'free-tablet': _lazy('Android tablets'), + 'paid-os': _lazy('Fully open mobile ecosystem'), + } + + ERRORS = {'both': _lazy(u'Cannot be free and paid.'), + 'none': _lazy(u'Please select a device.'), + 'packaged': _lazy(u'Packaged apps are only valid ' + u'for Firefox OS.')} + upload = forms.ModelChoiceField(widget=forms.HiddenInput, queryset=FileUpload.objects.filter(valid=True), error_messages={'invalid_choice': _lazy(u'There was an error with your' - ' upload. Please try again.')}) + u' upload. Please try' + u' again.')}) - def __init__(self, *args, **kw): - self.addon = kw.pop('addon', None) - self.is_packaged = kw.pop('is_packaged', False) - super(NewWebappForm, self).__init__(*args, **kw) + packaged = forms.BooleanField(required=False) + free = forms.MultipleChoiceField(choices=FREE, required=False) + paid = forms.MultipleChoiceField(choices=PAID, required=False) + + + def _add_error(self, msg): + self._errors['free'] = self._errors['paid'] = self.ERRORS[msg] + + + def _get_combined(self): + return set(self.cleaned_data.get('free', []) + + self.cleaned_data.get('paid', [])) + + def clean(self): + data = self.cleaned_data + + # Check that they didn't select both. + if data.get('free') and data.get('paid'): + self._add_error('both') + return + + # Check that they selected one. + if not data.get('free') and not data.get('paid'): + self._add_error('none') + self._errors['free'] = self._errors['paid'] = self.ERRORS['none'] + return + + # Packaged apps are only valid for firefox os. + if self.is_packaged(): + if not set(self._get_combined()).issubset(['paid-os', 'free-os']): + self._add_error('packaged') + return + + # Now run the packaged app check, done in clean, because + # clean_packaged needs to be processed first. + try: + pkg = parse_addon(data['upload'], self.addon) + except forms.ValidationError, e: + self._errors['upload'] = self.error_class(e.messages) + return - def clean_upload(self): - upload = self.cleaned_data['upload'] - if self.is_packaged: - pkg = parse_addon(upload, self.addon) ver = pkg.get('version') if (ver and self.addon and self.addon.versions.filter(version=ver).exists()): - raise forms.ValidationError( - _(u'Version %s already exists') % ver) + self._errors['upload'] = _(u'Version %s already exists') % ver + return else: # Throw an error if this is a dupe. # (JS sets manifest as `upload.name`.) - verify_app_domain(upload.name) - return upload + try: + verify_app_domain(data['upload'].name) + except forms.ValidationError, e: + self._errors['upload'] = self.error_class(e.messages) + return + + return data + + def get_devices(self): + """Returns a device based on the requested free or paid.""" + platforms = {'os': amo.DEVICE_MOBILE, + 'desktop': amo.DEVICE_DESKTOP, + 'phone': amo.DEVICE_MOBILE, + 'tablet': amo.DEVICE_TABLET} + return [platforms[t.split('-', 1)[1]] for t in self._get_combined()] + + def get_paid(self): + """Returns the premium type.""" + if self.cleaned_data.get('paid', False): + return amo.ADDON_PREMIUM + return amo.ADDON_FREE + + def is_packaged(self): + return self.cleaned_data.get('packaged', False) + + def __init__(self, *args, **kw): + self.addon = kw.pop('addon', None) + super(NewWebappForm, self).__init__(*args, **kw) + if not waffle.switch_is_active('allow-b2g-paid-submission'): + del self.fields['paid'] + + if not waffle.switch_is_active('allow-packaged-app-uploads'): + del self.fields['packaged'] class PaypalSetupForm(happyforms.Form): @@ -87,13 +182,6 @@ class PaypalSetupForm(happyforms.Form): return data -class PremiumTypeForm(happyforms.Form): - premium_type = forms.TypedChoiceField(coerce=lambda x: int(x), - choices=amo.ADDON_PREMIUM_TYPES.items(), - widget=forms.RadioSelect(), - label=_lazy(u'Will your app use payments?')) - - class UpsellForm(happyforms.Form): price = forms.ModelChoiceField(queryset=Price.objects.active(), label=_lazy(u'App Price'), diff --git a/mkt/submit/templates/submit/choose.html b/mkt/submit/templates/submit/choose.html deleted file mode 100644 index 66f7d003e9..0000000000 --- a/mkt/submit/templates/submit/choose.html +++ /dev/null @@ -1,73 +0,0 @@ -{% extends 'developers/base_impala.html' %} - -{% set hosted_url = 'https://developer.mozilla.org/en-US/docs/Apps/Manifest' %} -{# TODO(bug 7884448): Change this link when that bug gets closed. #} -{% set packaged_url = 'https://bugzilla.mozilla.org/show_bug.cgi?id=784448' %} - -{% set title = _('Submit an App') %} - -{% block title %}{{ hub_page_title(title) }}{% endblock %} - -{% block content %} - {{ hub_breadcrumbs(items=[(None, _('Submit App'))]) }} -
-

{{ _('Submit an App') }}

- {{ progress(request, addon=None, step=step) }} -
-
-

{{ _('Choose an App Type') }}

-
-
-

- {% trans url=url('submit.app.manifest') %} - If the app is hosted on your own server, - then your app type is
- Hosted - {% endtrans %} -

-

- {% trans %} - What's next: submit your app manifest URL - {% endtrans %} -

-

- {% trans %} - Learn more about app manifests on MDN. - {% endtrans %} -

- {# TODO(bug 784448): Remove when other a.soon is gone. #} -   -
-
-

- {% trans url=url('submit.app.package') %} - If the app is going to be hosted by Mozilla, - then your app type is
- Packaged - {% endtrans %} -

-

- {% trans %} - What's next: upload your packaged app - {% endtrans %} -

-

- {% trans %} - Learn more about packaged apps on MDN. - {% endtrans %} -

- Coming soon -
-
-
- - -
-{% endblock %} diff --git a/mkt/submit/templates/submit/manifest.html b/mkt/submit/templates/submit/manifest.html index 712edba0cd..fee6b50753 100644 --- a/mkt/submit/templates/submit/manifest.html +++ b/mkt/submit/templates/submit/manifest.html @@ -6,24 +6,56 @@ {% block title %}{{ hub_page_title(title) }}{% endblock %} +{% macro button(form, item) %} + +{% endmacro %} + {% block content %} {{ hub_breadcrumbs(items=[(None, _('Submit App'))]) }}

{{ _('Submit an App') }}

{{ progress(request, addon=None, step=step) }}
-
-

{{ _("Where's Your Manifest?") }}

-

- {% trans %} - Kick off things by creating your app's manifest and entering its URL - below. Learn about manifests. - {% endtrans %} -

-
+ + +
+
+ {% if waffle.switch('allow-b2g-paid-submission') %} +

{{ _('Free') }}

+ {% else %} +

{{ _('Device Type') }}

+ {% endif %} +
{{ form.errors.free }}
+ {% for item in form.fields['free'].choices %} + {{ button(form, item) }} + {% endfor %} +
+ + {% if waffle.switch('allow-b2g-paid-submission') %} + + {% endif %} +
+ +
+
+ {% if waffle.switch('allow-packaged-app-uploads') %} +

Hosted

+ {% endif %} +

{{ _("Submit your app manifest URL") }}

- {# TODO: Feel free to add more content, links to tips, sample manifests, builders. Please do. Really. #} -

- {% trans %} - Learn more about app manifests on MDN. - {% endtrans %} -

+ + +
+ {% if waffle.switch('allow-packaged-app-uploads') %} +

Packaged

+ + {% endif %} +
+ +
+ {{ csrf() }} + + +
+ {% trans %} + What's next: fill out the rest of your app's details + {% endtrans %} + +
+
+ +

+ {% trans %}Learn more about app manifests on MDN.{% endtrans %} + +

+ {% endblock %} diff --git a/mkt/submit/templates/submit/upload.html b/mkt/submit/templates/submit/upload.html deleted file mode 100644 index df618430f0..0000000000 --- a/mkt/submit/templates/submit/upload.html +++ /dev/null @@ -1,37 +0,0 @@ -{% extends 'developers/base_impala.html' %} - -{% set title = _('Upload Your App') %} -{% block title %}{{ hub_page_title(title) }}{% endblock %} - -{% block content %} - {{ hub_breadcrumbs(items=[(None, title)]) }} -
-

{{ title }}

- {{ progress(request, addon=None, step=step) }} -
-
-

{{ _("Where's Your Packaged App?") }}

-
- {{ csrf() }} -

- {% trans %} - Use the fields below to upload your packaged app. After upload, a - series of automated validation tests will be run on your file. - {% endtrans %} -

-
- - - {{ form.non_field_errors() }} - {{ form.upload.errors }} -
- -
-
-
-
-{% endblock %} diff --git a/mkt/submit/tests/test_forms.py b/mkt/submit/tests/test_forms.py new file mode 100644 index 0000000000..5df03ad576 --- /dev/null +++ b/mkt/submit/tests/test_forms.py @@ -0,0 +1,100 @@ +import mock +from nose.tools import eq_ + +import amo +import amo.tests +from files.models import FileUpload +from mkt.submit import forms + + +class TestNewWebappForm(amo.tests.TestCase): + + def setUp(self): + self.file = FileUpload.objects.create(valid=True) + + def test_not_free_or_paid(self): + form = forms.NewWebappForm({}) + assert not form.is_valid() + eq_(form.ERRORS['none'], form.errors['free']) + eq_(form.ERRORS['none'], form.errors['paid']) + + def test_not_paid(self): + form = forms.NewWebappForm({'paid': ['paid-os']}) + assert not form.is_valid() + eq_(form.ERRORS['none'], form.errors['free']) + eq_(form.ERRORS['none'], form.errors['paid']) + + def test_paid(self): + self.create_switch('allow-b2g-paid-submission') + form = forms.NewWebappForm({'paid': ['paid-os'], + 'upload': self.file.uuid}) + assert form.is_valid() + eq_(form.get_paid(), amo.ADDON_PREMIUM) + + def test_free(self): + self.create_switch('allow-b2g-paid-submission') + form = forms.NewWebappForm({'free': ['free-os'], + 'upload': self.file.uuid}) + assert form.is_valid() + eq_(form.get_paid(), amo.ADDON_FREE) + + def test_platform(self): + self.create_switch('allow-b2g-paid-submission') + for data, res in ( + ({'free': ['free-os']}, [amo.DEVICE_MOBILE]), + ({'paid': ['paid-os']}, [amo.DEVICE_MOBILE]), + ({'free': ['free-os', + 'free-phone']}, [amo.DEVICE_MOBILE]), + ({'free': ['free-phone', + 'free-tablet']}, + [amo.DEVICE_MOBILE, amo.DEVICE_TABLET]), + ): + data['upload'] = self.file.uuid + form = forms.NewWebappForm(data) + assert form.is_valid(), form.errors + assert set(res) == set(form.get_devices()) + + def test_both(self): + self.create_switch('allow-b2g-paid-submission') + form = forms.NewWebappForm({'paid': ['paid-os'], + 'free': ['free-os']}) + assert not form.is_valid() + eq_(form.ERRORS['both'], form.errors['free']) + eq_(form.ERRORS['both'], form.errors['paid']) + + def test_multiple(self): + form = forms.NewWebappForm({'free': ['free-os', + 'free-desktop'], + 'upload': self.file.uuid}) + assert form.is_valid() + + def test_not_packaged(self): + form = forms.NewWebappForm({'free': ['free-os'], + 'upload': self.file.uuid, + 'packaged': True}) + assert form.is_valid(), form.errors + assert not form.is_packaged() + + def test_not_packaged_allowed(self): + self.create_switch('allow-packaged-app-uploads') + form = forms.NewWebappForm({'free': ['free-os'], + 'upload': self.file.uuid}) + assert form.is_valid(), form.errors + assert not form.is_packaged() + + @mock.patch('mkt.submit.forms.parse_addon') + def test_packaged_allowed(self, parse_addon): + self.create_switch('allow-packaged-app-uploads') + form = forms.NewWebappForm({'free': ['free-os'], + 'upload': self.file.uuid, + 'packaged': True}) + assert form.is_valid() + assert form.is_packaged() + + def test_packaged_wrong_device(self): + self.create_switch('allow-packaged-app-uploads') + form = forms.NewWebappForm({'free': ['free-desktop'], + 'upload': self.file.uuid, + 'packaged': True}) + assert not form.is_valid(), form.errors + eq_(form.ERRORS['packaged'], form.errors['paid']) diff --git a/mkt/submit/tests/test_views.py b/mkt/submit/tests/test_views.py index ef8b9d012f..3c45b76688 100644 --- a/mkt/submit/tests/test_views.py +++ b/mkt/submit/tests/test_views.py @@ -124,20 +124,16 @@ class TestTerms(TestSubmit): self._test_progress_display([], 'terms') def test_agree(self): - self.create_switch(name='allow-packaged-app-uploads') - r = self.client.post(self.url, {'read_dev_agreement': True}) - self.assert3xx(r, reverse('submit.app.choose')) + self.client.post(self.url, {'read_dev_agreement': True}) dt = self.get_user().read_dev_agreement assert close_to_now(dt), ( 'Expected date of agreement read to be close to now. Was %s' % dt) eq_(UserNotification.objects.count(), 0) def test_agree_and_sign_me_up(self): - self.create_switch(name='allow-packaged-app-uploads') - r = self.client.post(self.url, {'read_dev_agreement': - datetime.datetime.now(), - 'newsletter': True}) - self.assert3xx(r, reverse('submit.app.choose')) + self.client.post(self.url, {'read_dev_agreement': + datetime.datetime.now(), + 'newsletter': True}) dt = self.get_user().read_dev_agreement assert close_to_now(dt), ( 'Expected date of agreement read to be close to now. Was %s' % dt) @@ -190,16 +186,12 @@ class TestManifest(TestSubmit): # So jump me to the Manifest step. r = self.client.get(reverse('submit.app'), follow=True) self.assert3xx(r, reverse('submit.app.manifest')) - # Now with waffles! - self.create_switch(name='allow-packaged-app-uploads') - r = self.client.get(reverse('submit.app'), follow=True) - self.assert3xx(r, reverse('submit.app.choose')) def test_page(self): self._step() r = self.client.get(self.url) eq_(r.status_code, 200) - eq_(pq(r.content)('#submit-manifest').length, 1) + eq_(pq(r.content)('#upload-file').length, 1) def test_progress_display(self): self._step() @@ -208,12 +200,11 @@ class TestManifest(TestSubmit): class UploadAddon(object): - def post(self, desktop_platforms=[amo.PLATFORM_ALL], mobile_platforms=[], - expect_errors=False): - d = dict(upload=self.upload.pk, - desktop_platforms=[p.id for p in desktop_platforms], - mobile_platforms=[p.id for p in mobile_platforms]) - r = self.client.post(self.url, d, follow=True) + def post(self, expect_errors=False, data=None): + if data is None: + data = {'free': ['free-desktop']} + data.update(upload=self.upload.pk) + r = self.client.post(self.url, data, follow=True) eq_(r.status_code, 200) if not expect_errors: # Show any unexpected form errors. @@ -238,9 +229,9 @@ class BaseWebAppTest(BaseUploadTest, UploadAddon, amo.tests.TestCase): self.client.post(reverse('submit.app.terms'), {'read_dev_agreement': True}) - def post_addon(self): + def post_addon(self, data=None): eq_(Addon.objects.count(), 0) - self.post() + self.post(data=data) return Addon.objects.get() @@ -320,6 +311,20 @@ class TestCreateWebApp(BaseWebAppTest): eq_(len(files), 1) eq_(files[0].status, amo.STATUS_PENDING) + def test_set_platform(self): + app = self.post_addon({'free': ['free-tablet', 'free-desktop']}) + eq_(set(app.device_types), + set([amo.DEVICE_TABLET, amo.DEVICE_DESKTOP])) + + def test_free(self): + app = self.post_addon({'free': ['free-os']}) + eq_(app.premium_type, amo.ADDON_FREE) + + def test_premium(self): + self.create_switch('allow-b2g-paid-submission') + app = self.post_addon({'paid': ['paid-os']}) + eq_(app.premium_type, amo.ADDON_PREMIUM) + class TestCreateWebAppFromManifest(BaseWebAppTest): @@ -380,16 +385,16 @@ class BasePackagedAppTest(BaseUploadTest, UploadAddon, amo.tests.TestCase): self.package = self.packaged_app_path('mozball.zip') self.upload = self.get_upload(abspath=self.package) self.upload.update(name='mozball.zip', is_webapp=True) - self.url = reverse('submit.app.package') + self.url = reverse('submit.app.manifest') assert self.client.login(username='regular@mozilla.com', password='password') # Complete first step. self.client.post(reverse('submit.app.terms'), {'read_dev_agreement': True}) - def post_addon(self): + def post_addon(self, data=None): eq_(Addon.objects.count(), 1) - self.post() + self.post(data=data) return Addon.objects.order_by('-id')[0] def setup_files(self): @@ -413,7 +418,7 @@ class TestCreatePackagedApp(BasePackagedAppTest): reverse('submit.app.details', args=[webapp.app_slug])) def test_app_from_uploaded_package(self): - addon = self.post_addon() + addon = self.post_addon(data={'packaged': True, 'free': ['free-os']}) eq_(addon.type, amo.ADDON_WEBAPP) eq_(addon.current_version.version, '1.0') eq_(addon.is_packaged, True) @@ -429,7 +434,7 @@ class TestCreatePackagedApp(BasePackagedAppTest): @mock.patch('mkt.submit.forms.verify_app_domain') def test_packaged_app_not_unique_by_domain(self, _verify): - self.post() + self.post(data={'packaged': True, 'free': ['free-os']}) assert not _verify.called, ('`verify_app_domain` should not be called' ' for packaged apps.') diff --git a/mkt/submit/urls.py b/mkt/submit/urls.py index b876a32373..a33d1ba775 100644 --- a/mkt/submit/urls.py +++ b/mkt/submit/urls.py @@ -31,8 +31,6 @@ urlpatterns = decorate(write, patterns('', url('^app$', views.submit, name='submit.app'), url('^app/proceed$', views.proceed, name='submit.app.proceed'), url('^app/terms$', views.terms, name='submit.app.terms'), - url('^app/choose$', views.choose, name='submit.app.choose'), url('^app/manifest$', views.manifest, name='submit.app.manifest'), - url('^app/package$', views.package, name='submit.app.package'), ('^app/', include(submit_apps_patterns)), )) diff --git a/mkt/submit/views.py b/mkt/submit/views.py index 068959d93e..24635cbd24 100644 --- a/mkt/submit/views.py +++ b/mkt/submit/views.py @@ -37,8 +37,6 @@ def submit(request): # If dev has already agreed, continue to next step. user = UserProfile.objects.get(pk=request.user.id) if user.read_dev_agreement: - if waffle.switch_is_active('allow-packaged-app-uploads'): - return redirect('submit.app.choose') return redirect('submit.app.manifest') else: return redirect('submit.app.terms') @@ -66,8 +64,6 @@ def terms(request): # If dev has already agreed, continue to next step. if (getattr(request, 'amo_user', None) and request.amo_user.read_dev_agreement): - if waffle.switch_is_active('allow-packaged-app-uploads'): - return redirect('submit.app.choose') return redirect('submit.app.manifest') agreement_form = forms.DevAgreementForm( @@ -75,8 +71,6 @@ def terms(request): instance=request.amo_user) if request.POST and agreement_form.is_valid(): agreement_form.save() - if waffle.switch_is_active('allow-packaged-app-uploads'): - return redirect('submit.app.choose') return redirect('submit.app.manifest') return jingo.render(request, 'submit/terms.html', { 'step': 'terms', @@ -84,27 +78,27 @@ def terms(request): }) -@login_required -@read_dev_agreement_required -@submit_step('manifest') -def choose(request): - if not waffle.switch_is_active('allow-packaged-app-uploads'): - return redirect('submit.app.manifest') - return jingo.render(request, 'submit/choose.html', { - 'step': 'manifest', - }) - - @login_required @read_dev_agreement_required @submit_step('manifest') @transaction.commit_on_success def manifest(request): form = forms.NewWebappForm(request.POST or None) + if request.method == 'POST' and form.is_valid(): addon = Addon.from_upload( form.cleaned_data['upload'], - [Platform.objects.get(id=amo.PLATFORM_ALL.id)]) + [Platform.objects.get(id=amo.PLATFORM_ALL.id)], + is_packaged=form.is_packaged()) + + # Set the device type. + for device in form.get_devices(): + addon.addondevicetype_set.create(device_type=device.id) + + # Set the premium type, only bother if it's not free. + premium = form.get_paid() + if premium: + addon.update(premium_type=premium) if addon.has_icon_in_manifest(): # Fetch the icon, do polling. @@ -123,37 +117,7 @@ def manifest(request): return jingo.render(request, 'submit/manifest.html', { 'step': 'manifest', - 'form': form, - }) - - -@login_required -@read_dev_agreement_required -@submit_step('manifest') -def package(request): - form = forms.NewWebappForm(request.POST or None, is_packaged=True) - if request.method == 'POST' and form.is_valid(): - addon = Addon.from_upload( - form.cleaned_data['upload'], - [Platform.objects.get(id=amo.PLATFORM_ALL.id)], is_packaged=True) - - if addon.has_icon_in_manifest(): - # Fetch the icon, do polling. - addon.update(icon_type='image/png') - tasks.fetch_icon.delay(addon) - else: - # In this case there is no need to do any polling. - addon.update(icon_type='') - - AddonUser(addon=addon, user=request.amo_user).save() - AppSubmissionChecklist.objects.create(addon=addon, terms=True, - manifest=True) - - return redirect('submit.app.details', addon.app_slug) - - return jingo.render(request, 'submit/upload.html', { - 'form': form, - 'step': 'manifest', + 'form': form })