2010-12-31 01:05:56 +03:00
|
|
|
# -*- coding: utf8 -*-
|
2010-11-20 02:55:39 +03:00
|
|
|
import json
|
2010-12-10 03:36:00 +03:00
|
|
|
import os
|
2010-10-18 21:57:48 +04:00
|
|
|
import re
|
2010-12-30 20:54:28 +03:00
|
|
|
import shutil
|
2010-10-11 22:24:41 +04:00
|
|
|
import socket
|
2010-12-30 20:54:28 +03:00
|
|
|
import tempfile
|
2011-01-11 00:00:24 +03:00
|
|
|
from datetime import datetime
|
2010-11-06 00:51:28 +03:00
|
|
|
from decimal import Decimal
|
2010-10-08 07:08:41 +04:00
|
|
|
|
2010-10-20 21:40:20 +04:00
|
|
|
from django import forms
|
2010-10-27 00:21:46 +04:00
|
|
|
from django.conf import settings
|
2010-09-30 07:12:18 +04:00
|
|
|
from django.utils import translation
|
2010-09-28 02:35:06 +04:00
|
|
|
|
2010-10-11 22:24:41 +04:00
|
|
|
import mock
|
2010-11-18 00:41:34 +03:00
|
|
|
from nose.tools import eq_, assert_not_equal, assert_raises
|
2011-01-08 00:26:57 +03:00
|
|
|
from nose.plugins.attrib import attr
|
2010-12-10 03:36:00 +03:00
|
|
|
from PIL import Image
|
2010-09-28 02:35:06 +04:00
|
|
|
from pyquery import PyQuery as pq
|
2010-11-23 05:27:41 +03:00
|
|
|
from redisutils import mock_redis, reset_redis
|
2010-09-28 02:35:06 +04:00
|
|
|
import test_utils
|
|
|
|
|
|
|
|
import amo
|
2010-11-20 06:18:56 +03:00
|
|
|
import files.tests
|
2010-10-11 22:24:41 +04:00
|
|
|
import paypal
|
2010-09-28 02:35:06 +04:00
|
|
|
from amo.urlresolvers import reverse
|
2010-12-10 22:52:26 +03:00
|
|
|
from amo.tests.test_helpers import get_image_path
|
2010-12-07 00:55:41 +03:00
|
|
|
from addons import cron
|
2011-01-11 02:33:34 +03:00
|
|
|
from addons.forms import AddonFormBasic
|
2010-12-10 06:51:46 +03:00
|
|
|
from addons.models import Addon, AddonUser, Charity, Category, AddonCategory
|
2010-11-23 04:45:12 +03:00
|
|
|
from addons.utils import ReverseNameLookup
|
2010-12-01 23:45:43 +03:00
|
|
|
from applications.models import Application, AppVersion
|
2010-12-01 20:56:49 +03:00
|
|
|
from devhub.forms import ContribForm, LicenseForm
|
2010-12-16 23:30:44 +03:00
|
|
|
from devhub.models import ActivityLog, SubmitStep
|
2010-12-30 00:13:43 +03:00
|
|
|
from files.models import File, FileUpload, Platform, FileValidation
|
2011-01-03 23:58:15 +03:00
|
|
|
from reviews.models import Review
|
2010-11-11 22:33:39 +03:00
|
|
|
from tags.models import Tag
|
2010-09-28 02:35:06 +04:00
|
|
|
from users.models import UserProfile
|
2010-10-28 22:04:20 +04:00
|
|
|
from versions.models import ApplicationsVersions, License, Version
|
2010-09-28 02:35:06 +04:00
|
|
|
|
|
|
|
|
2010-12-21 01:23:33 +03:00
|
|
|
def assert_no_validation_errors(validation):
|
|
|
|
"""Assert that the validation (JSON) does not contain a traceback.
|
|
|
|
|
|
|
|
Note that this does not test whether the addon passed
|
|
|
|
validation or not.
|
|
|
|
"""
|
|
|
|
if hasattr(validation, 'task_error'):
|
|
|
|
# FileUpload object:
|
|
|
|
error = validation.task_error
|
|
|
|
else:
|
|
|
|
# Upload detail - JSON output
|
|
|
|
error = validation['error']
|
|
|
|
if error:
|
2010-12-20 23:47:01 +03:00
|
|
|
print '-' * 70
|
2010-12-21 01:23:33 +03:00
|
|
|
print error
|
2010-12-20 23:47:01 +03:00
|
|
|
print '-' * 70
|
2010-12-21 01:23:33 +03:00
|
|
|
raise AssertionError("Unexpected task error: %s" %
|
|
|
|
error.rstrip().split("\n")[-1])
|
|
|
|
|
|
|
|
|
2011-01-12 21:44:00 +03:00
|
|
|
def assert_close_to_now(dt):
|
|
|
|
"""
|
|
|
|
Compare a datetime with datetime.now, with resolution up to the minute.
|
|
|
|
"""
|
|
|
|
eq_(dt.timetuple()[:5], datetime.now().timetuple()[:5])
|
|
|
|
|
|
|
|
|
2010-10-02 08:23:17 +04:00
|
|
|
class HubTest(test_utils.TestCase):
|
2010-10-28 22:04:20 +04:00
|
|
|
fixtures = ['browse/nameless-addon', 'base/users']
|
2010-09-28 02:35:06 +04:00
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
translation.activate('en-US')
|
|
|
|
self.url = reverse('devhub.index')
|
|
|
|
self.login_as_developer()
|
|
|
|
eq_(self.client.get(self.url).status_code, 200)
|
|
|
|
self.user_profile = UserProfile.objects.get(id=999)
|
|
|
|
|
|
|
|
def login_as_developer(self):
|
|
|
|
self.client.login(username='regular@mozilla.com', password='password')
|
|
|
|
|
2010-11-22 06:10:56 +03:00
|
|
|
def clone_addon(self, num, addon_id=57132):
|
|
|
|
ids = []
|
2010-12-31 04:02:31 +03:00
|
|
|
for i in range(num):
|
2010-09-28 02:35:06 +04:00
|
|
|
addon = Addon.objects.get(id=addon_id)
|
|
|
|
addon.id = addon.guid = None
|
|
|
|
addon.save()
|
|
|
|
AddonUser.objects.create(user=self.user_profile, addon=addon)
|
|
|
|
new_addon = Addon.objects.get(id=addon.id)
|
2010-11-22 06:10:56 +03:00
|
|
|
new_addon.name = str(addon.id)
|
2010-09-28 02:35:06 +04:00
|
|
|
new_addon.save()
|
2010-11-22 06:10:56 +03:00
|
|
|
ids.append(addon.id)
|
|
|
|
return ids
|
2010-09-28 02:35:06 +04:00
|
|
|
|
|
|
|
|
|
|
|
class TestNav(HubTest):
|
|
|
|
|
|
|
|
def test_navbar(self):
|
|
|
|
r = self.client.get(self.url)
|
|
|
|
doc = pq(r.content)
|
|
|
|
eq_(doc('#navbar').length, 1)
|
|
|
|
|
|
|
|
def test_no_addons(self):
|
|
|
|
"""Check that no add-ons are displayed for this user."""
|
|
|
|
r = self.client.get(self.url)
|
|
|
|
doc = pq(r.content)
|
|
|
|
assert_not_equal(doc('#navbar ul li.top a').eq(0).text(),
|
|
|
|
'My Add-ons',
|
|
|
|
'My Add-ons menu should not be visible if user has no add-ons.')
|
|
|
|
|
|
|
|
def test_my_addons(self):
|
|
|
|
"""Check that the correct items are listed for the My Add-ons menu."""
|
|
|
|
# Assign this add-on to the current user profile.
|
|
|
|
addon = Addon.objects.get(id=57132)
|
|
|
|
AddonUser.objects.create(user=self.user_profile, addon=addon)
|
|
|
|
|
|
|
|
r = self.client.get(self.url)
|
|
|
|
doc = pq(r.content)
|
|
|
|
|
|
|
|
# Check the anchor for the 'My Add-ons' menu item.
|
|
|
|
eq_(doc('#navbar ul li.top a').eq(0).text(), 'My Add-ons')
|
|
|
|
|
|
|
|
# Check the anchor for the single add-on.
|
2010-12-20 23:47:01 +03:00
|
|
|
edit_url = reverse('devhub.addons.edit', args=[addon.slug])
|
2010-09-28 02:35:06 +04:00
|
|
|
eq_(doc('#navbar ul li.top li a').eq(0).attr('href'), edit_url)
|
|
|
|
|
|
|
|
# Create 6 add-ons.
|
|
|
|
self.clone_addon(6)
|
|
|
|
|
|
|
|
r = self.client.get(self.url)
|
|
|
|
doc = pq(r.content)
|
|
|
|
|
|
|
|
# There should be 8 items in this menu.
|
2010-09-28 03:35:15 +04:00
|
|
|
eq_(doc('#navbar ul li.top').eq(0).find('ul li').length, 8)
|
2010-09-28 02:35:06 +04:00
|
|
|
|
|
|
|
# This should be the 8th anchor, after the 7 addons.
|
2010-09-28 03:35:15 +04:00
|
|
|
eq_(doc('#navbar ul li.top').eq(0).find('li a').eq(7).text(),
|
2010-09-28 02:35:06 +04:00
|
|
|
'Submit a New Add-on')
|
|
|
|
|
2010-09-28 04:13:29 +04:00
|
|
|
self.clone_addon(1)
|
2010-09-28 02:35:06 +04:00
|
|
|
|
|
|
|
r = self.client.get(self.url)
|
|
|
|
doc = pq(r.content)
|
2010-09-28 03:35:15 +04:00
|
|
|
eq_(doc('#navbar ul li.top').eq(0).find('li a').eq(7).text(),
|
2010-09-28 02:35:06 +04:00
|
|
|
'more add-ons...')
|
|
|
|
|
|
|
|
|
|
|
|
class TestDashboard(HubTest):
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
super(TestDashboard, self).setUp()
|
|
|
|
self.url = reverse('devhub.addons')
|
|
|
|
eq_(self.client.get(self.url).status_code, 200)
|
|
|
|
|
2010-11-30 01:18:05 +03:00
|
|
|
def get_action_links(self, addon_id):
|
|
|
|
r = self.client.get(self.url)
|
|
|
|
doc = pq(r.content)
|
|
|
|
links = [a.text.strip() for a in
|
|
|
|
doc('.item[data-addonid=%s] .item-actions li > a' % addon_id)]
|
|
|
|
return links
|
|
|
|
|
2010-09-28 02:35:06 +04:00
|
|
|
def test_no_addons(self):
|
|
|
|
"""Check that no add-ons are displayed for this user."""
|
|
|
|
r = self.client.get(self.url)
|
|
|
|
doc = pq(r.content)
|
|
|
|
eq_(doc('.item item').length, 0)
|
|
|
|
|
2010-11-22 06:10:56 +03:00
|
|
|
def test_addon_pagination(self):
|
2010-09-28 02:35:06 +04:00
|
|
|
"""Check that the correct info. is displayed for each add-on:
|
|
|
|
namely, that add-ons are paginated at 10 items per page, and that
|
|
|
|
when there is more than one page, the 'Sort by' header and pagination
|
|
|
|
footer appear.
|
|
|
|
|
|
|
|
"""
|
|
|
|
# Create 10 add-ons.
|
2010-11-23 03:40:53 +03:00
|
|
|
self.clone_addon(10)
|
2010-09-28 02:35:06 +04:00
|
|
|
r = self.client.get(self.url)
|
|
|
|
doc = pq(r.content)
|
|
|
|
eq_(len(doc('.item .item-info')), 10)
|
|
|
|
eq_(doc('#addon-list-options').length, 0)
|
|
|
|
eq_(doc('.listing-footer .pagination').length, 0)
|
|
|
|
|
|
|
|
# Create 5 add-ons.
|
|
|
|
self.clone_addon(5)
|
|
|
|
r = self.client.get(self.url + '?page=2')
|
|
|
|
doc = pq(r.content)
|
|
|
|
eq_(len(doc('.item .item-info')), 5)
|
|
|
|
eq_(doc('#addon-list-options').length, 1)
|
|
|
|
eq_(doc('.listing-footer .pagination').length, 1)
|
2010-09-30 07:12:18 +04:00
|
|
|
|
2010-11-25 02:42:15 +03:00
|
|
|
def test_show_hide_statistics(self):
|
|
|
|
a_pk = self.clone_addon(1)[0]
|
|
|
|
|
|
|
|
# when Active and Public show statistics
|
2010-12-06 23:52:50 +03:00
|
|
|
Addon.objects.get(pk=a_pk).update(disabled_by_user=False,
|
2010-11-25 02:42:15 +03:00
|
|
|
status=amo.STATUS_PUBLIC)
|
2010-11-30 01:18:05 +03:00
|
|
|
links = self.get_action_links(a_pk)
|
2010-11-25 02:42:15 +03:00
|
|
|
assert 'Statistics' in links, ('Unexpected: %r' % links)
|
|
|
|
|
|
|
|
# when Active and Incomplete hide statistics
|
2010-12-06 23:52:50 +03:00
|
|
|
Addon.objects.get(pk=a_pk).update(disabled_by_user=False,
|
2010-11-25 02:42:15 +03:00
|
|
|
status=amo.STATUS_NULL)
|
2010-11-30 01:18:05 +03:00
|
|
|
links = self.get_action_links(a_pk)
|
2010-11-25 02:42:15 +03:00
|
|
|
assert 'Statistics' not in links, ('Unexpected: %r' % links)
|
|
|
|
|
2010-11-30 01:18:05 +03:00
|
|
|
def test_complete_addon_item(self):
|
|
|
|
a_pk = self.clone_addon(1)[0]
|
|
|
|
a = Addon.objects.get(pk=a_pk)
|
|
|
|
r = self.client.get(self.url)
|
|
|
|
doc = pq(r.content)
|
|
|
|
eq_(a.status, amo.STATUS_PUBLIC)
|
|
|
|
assert doc('.item[data-addonid=%s] ul.item-details' % a_pk)
|
|
|
|
assert doc('.item[data-addonid=%s] h4 a' % a_pk)
|
|
|
|
assert not doc('.item[data-addonid=%s] > p' % a_pk)
|
|
|
|
|
|
|
|
def test_incomplete_addon_item(self):
|
|
|
|
a_pk = self.clone_addon(1)[0]
|
|
|
|
Addon.objects.get(pk=a_pk).update(status=amo.STATUS_NULL)
|
|
|
|
r = self.client.get(self.url)
|
|
|
|
doc = pq(r.content)
|
|
|
|
assert not doc('.item[data-addonid=%s] ul.item-details' % a_pk)
|
|
|
|
assert not doc('.item[data-addonid=%s] h4 a' % a_pk)
|
|
|
|
assert doc('.item[data-addonid=%s] > p' % a_pk)
|
|
|
|
|
2010-09-30 07:12:18 +04:00
|
|
|
|
2010-10-28 22:04:20 +04:00
|
|
|
class TestUpdateCompatibility(test_utils.TestCase):
|
|
|
|
fixtures = ['base/apps', 'base/users', 'base/addon_4594_a9',
|
|
|
|
'base/addon_3615']
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
self.url = reverse('devhub.addons')
|
|
|
|
|
|
|
|
def test_no_compat(self):
|
|
|
|
assert self.client.login(username='admin@mozilla.com',
|
|
|
|
password='password')
|
|
|
|
r = self.client.get(self.url)
|
|
|
|
doc = pq(r.content)
|
2010-11-18 20:22:34 +03:00
|
|
|
assert not doc('.item[data-addonid=4594] li.compat')
|
2010-10-28 22:04:20 +04:00
|
|
|
a = Addon.objects.get(pk=4594)
|
|
|
|
r = self.client.get(reverse('devhub.ajax.compat.update',
|
2010-12-20 23:47:01 +03:00
|
|
|
args=[a.slug, a.current_version.id]))
|
2010-10-28 22:04:20 +04:00
|
|
|
eq_(r.status_code, 404)
|
2010-12-20 23:47:01 +03:00
|
|
|
r = self.client.get(reverse('devhub.ajax.compat.status',
|
|
|
|
args=[a.slug]))
|
2010-11-18 20:22:34 +03:00
|
|
|
eq_(r.status_code, 404)
|
2010-10-28 22:04:20 +04:00
|
|
|
|
|
|
|
def test_compat(self):
|
|
|
|
a = Addon.objects.get(pk=3615)
|
|
|
|
assert self.client.login(username='del@icio.us', password='password')
|
|
|
|
|
|
|
|
r = self.client.get(self.url)
|
|
|
|
doc = pq(r.content)
|
|
|
|
cu = doc('.item[data-addonid=3615] .tooltip.compat-update')
|
|
|
|
assert cu
|
|
|
|
|
|
|
|
update_url = reverse('devhub.ajax.compat.update',
|
2010-12-20 23:47:01 +03:00
|
|
|
args=[a.slug, a.current_version.id])
|
2010-10-28 22:04:20 +04:00
|
|
|
eq_(cu.attr('data-updateurl'), update_url)
|
|
|
|
|
2010-12-20 23:47:01 +03:00
|
|
|
status_url = reverse('devhub.ajax.compat.status', args=[a.slug])
|
2010-10-28 22:04:20 +04:00
|
|
|
eq_(doc('.item[data-addonid=3615] li.compat').attr('data-src'),
|
|
|
|
status_url)
|
|
|
|
|
|
|
|
assert doc('.item[data-addonid=3615] .compat-update-modal')
|
|
|
|
|
|
|
|
def test_incompat(self):
|
|
|
|
av = ApplicationsVersions.objects.get(pk=47881)
|
|
|
|
av.max = AppVersion.objects.get(pk=97) # Firefox 2.0
|
|
|
|
av.save()
|
|
|
|
assert self.client.login(username='del@icio.us', password='password')
|
|
|
|
r = self.client.get(self.url)
|
|
|
|
doc = pq(r.content)
|
|
|
|
assert doc('.item[data-addonid=3615] .tooltip.compat-error')
|
|
|
|
|
|
|
|
|
2010-10-20 21:40:20 +04:00
|
|
|
def formset(*args, **kw):
|
|
|
|
"""
|
|
|
|
Build up a formset-happy POST.
|
|
|
|
|
|
|
|
*args is a sequence of forms going into the formset.
|
|
|
|
prefix and initial_count can be set in **kw.
|
|
|
|
"""
|
|
|
|
prefix = kw.pop('prefix', 'form')
|
2010-12-31 04:02:31 +03:00
|
|
|
total_count = kw.pop('total_count', len(args))
|
2010-10-21 21:05:30 +04:00
|
|
|
initial_count = kw.pop('initial_count', len(args))
|
2010-12-31 04:02:31 +03:00
|
|
|
data = {prefix + '-TOTAL_FORMS': total_count,
|
2010-10-20 21:40:20 +04:00
|
|
|
prefix + '-INITIAL_FORMS': initial_count}
|
|
|
|
for idx, d in enumerate(args):
|
|
|
|
data.update(('%s-%s-%s' % (prefix, idx, k), v)
|
|
|
|
for k, v in d.items())
|
|
|
|
data.update(kw)
|
|
|
|
return data
|
|
|
|
|
|
|
|
|
2010-11-13 07:18:33 +03:00
|
|
|
class TestDevRequired(test_utils.TestCase):
|
|
|
|
fixtures = ['base/apps', 'base/users', 'base/addon_3615']
|
|
|
|
|
|
|
|
def setUp(self):
|
2010-12-20 23:47:01 +03:00
|
|
|
self.get_url = reverse('devhub.addons.payments', args=['a3615'])
|
|
|
|
self.post_url = reverse('devhub.addons.payments.disable',
|
|
|
|
args=['a3615'])
|
2010-11-13 07:18:33 +03:00
|
|
|
assert self.client.login(username='del@icio.us', password='password')
|
|
|
|
self.addon = Addon.objects.get(id=3615)
|
|
|
|
self.au = AddonUser.objects.get(user__email='del@icio.us',
|
|
|
|
addon=self.addon)
|
|
|
|
eq_(self.au.role, amo.AUTHOR_ROLE_OWNER)
|
|
|
|
|
|
|
|
def test_anon(self):
|
|
|
|
self.client.logout()
|
|
|
|
r = self.client.get(self.get_url, follow=True)
|
|
|
|
login = reverse('users.login')
|
|
|
|
self.assertRedirects(r, '%s?to=%s' % (login, self.get_url))
|
|
|
|
|
|
|
|
def test_dev_get(self):
|
|
|
|
eq_(self.client.get(self.get_url).status_code, 200)
|
|
|
|
|
|
|
|
def test_dev_post(self):
|
|
|
|
self.assertRedirects(self.client.post(self.post_url), self.get_url)
|
|
|
|
|
|
|
|
def test_viewer_get(self):
|
|
|
|
self.au.role = amo.AUTHOR_ROLE_VIEWER
|
|
|
|
self.au.save()
|
|
|
|
eq_(self.client.get(self.get_url).status_code, 200)
|
|
|
|
|
|
|
|
def test_viewer_post(self):
|
|
|
|
self.au.role = amo.AUTHOR_ROLE_VIEWER
|
|
|
|
self.au.save()
|
|
|
|
eq_(self.client.post(self.get_url).status_code, 403)
|
|
|
|
|
2010-12-29 19:56:10 +03:00
|
|
|
def test_disabled_post_dev(self):
|
|
|
|
self.addon.update(status=amo.STATUS_DISABLED)
|
|
|
|
eq_(self.client.post(self.get_url).status_code, 403)
|
|
|
|
|
|
|
|
def test_disabled_post_admin(self):
|
|
|
|
self.addon.update(status=amo.STATUS_DISABLED)
|
|
|
|
assert self.client.login(username='admin@mozilla.com',
|
|
|
|
password='password')
|
|
|
|
self.assertRedirects(self.client.post(self.post_url), self.get_url)
|
|
|
|
|
2010-11-13 07:18:33 +03:00
|
|
|
|
2010-09-30 07:12:18 +04:00
|
|
|
class TestOwnership(test_utils.TestCase):
|
|
|
|
fixtures = ['base/apps', 'base/users', 'base/addon_3615']
|
|
|
|
|
|
|
|
def setUp(self):
|
2010-12-20 23:47:01 +03:00
|
|
|
self.url = reverse('devhub.addons.owner', args=['a3615'])
|
2010-09-30 07:12:18 +04:00
|
|
|
assert self.client.login(username='del@icio.us', password='password')
|
2010-10-05 23:24:31 +04:00
|
|
|
self.addon = Addon.objects.get(id=3615)
|
|
|
|
self.version = self.addon.current_version
|
2010-09-30 07:12:18 +04:00
|
|
|
|
|
|
|
def formset(self, *args, **kw):
|
2010-10-20 21:40:20 +04:00
|
|
|
defaults = {'builtin': License.OTHER, 'text': 'filler'}
|
|
|
|
defaults.update(kw)
|
|
|
|
return formset(*args, **defaults)
|
2010-09-30 07:12:18 +04:00
|
|
|
|
2010-10-05 23:24:31 +04:00
|
|
|
def get_version(self):
|
|
|
|
return Version.objects.no_cache().get(id=self.version.id)
|
|
|
|
|
2010-10-07 02:37:36 +04:00
|
|
|
def get_addon(self):
|
|
|
|
return Addon.objects.no_cache().get(id=self.addon.id)
|
|
|
|
|
|
|
|
|
|
|
|
class TestEditPolicy(TestOwnership):
|
|
|
|
|
|
|
|
def formset(self, *args, **kw):
|
|
|
|
init = self.client.get(self.url).context['user_form'].initial_forms
|
|
|
|
args = args + tuple(f.initial for f in init)
|
|
|
|
return super(TestEditPolicy, self).formset(*args, **kw)
|
|
|
|
|
|
|
|
def test_edit_eula(self):
|
|
|
|
old_eula = self.addon.eula
|
|
|
|
data = self.formset(eula='new eula', has_eula=True)
|
|
|
|
r = self.client.post(self.url, data)
|
|
|
|
eq_(r.status_code, 302)
|
|
|
|
addon = self.get_addon()
|
|
|
|
eq_(unicode(addon.eula), 'new eula')
|
|
|
|
eq_(addon.eula.id, old_eula.id)
|
|
|
|
|
|
|
|
def test_delete_eula(self):
|
|
|
|
assert self.addon.eula
|
|
|
|
r = self.client.post(self.url, self.formset(has_eula=False))
|
|
|
|
eq_(r.status_code, 302)
|
|
|
|
eq_(self.get_addon().eula, None)
|
2010-11-30 03:37:00 +03:00
|
|
|
|
2010-10-05 23:24:31 +04:00
|
|
|
|
|
|
|
class TestEditLicense(TestOwnership):
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
super(TestEditLicense, self).setUp()
|
|
|
|
self.version.license = None
|
|
|
|
self.version.save()
|
|
|
|
self.license = License.objects.create(builtin=1, name='bsd',
|
2010-12-01 20:56:49 +03:00
|
|
|
url='license.url', on_form=True)
|
2010-10-05 23:24:31 +04:00
|
|
|
|
|
|
|
def formset(self, *args, **kw):
|
|
|
|
init = self.client.get(self.url).context['user_form'].initial_forms
|
|
|
|
args = args + tuple(f.initial for f in init)
|
2010-10-13 00:53:05 +04:00
|
|
|
kw['initial_count'] = len(init)
|
2010-10-05 23:24:31 +04:00
|
|
|
data = super(TestEditLicense, self).formset(*args, **kw)
|
|
|
|
if 'text' not in kw:
|
|
|
|
del data['text']
|
|
|
|
return data
|
|
|
|
|
|
|
|
def test_success_add_builtin(self):
|
|
|
|
data = self.formset(builtin=1)
|
|
|
|
r = self.client.post(self.url, data)
|
|
|
|
eq_(r.status_code, 302)
|
|
|
|
eq_(self.license, self.get_version().license)
|
2010-11-29 23:59:13 +03:00
|
|
|
eq_(ActivityLog.objects.filter(
|
|
|
|
action=amo.LOG.CHANGE_LICENSE.id).count(), 1)
|
2010-10-05 23:24:31 +04:00
|
|
|
|
|
|
|
def test_success_add_custom(self):
|
|
|
|
data = self.formset(builtin=License.OTHER, text='text', name='name')
|
|
|
|
r = self.client.post(self.url, data)
|
|
|
|
eq_(r.status_code, 302)
|
|
|
|
license = self.get_version().license
|
|
|
|
eq_(unicode(license.text), 'text')
|
|
|
|
eq_(unicode(license.name), 'name')
|
|
|
|
eq_(license.builtin, License.OTHER)
|
|
|
|
|
|
|
|
def test_success_edit_custom(self):
|
|
|
|
data = self.formset(builtin=License.OTHER, text='text', name='name')
|
|
|
|
r = self.client.post(self.url, data)
|
|
|
|
license_one = self.get_version().license
|
|
|
|
|
|
|
|
data = self.formset(builtin=License.OTHER, text='woo', name='name')
|
|
|
|
r = self.client.post(self.url, data)
|
|
|
|
eq_(r.status_code, 302)
|
|
|
|
license_two = self.get_version().license
|
|
|
|
eq_(unicode(license_two.text), 'woo')
|
|
|
|
eq_(unicode(license_two.name), 'name')
|
|
|
|
eq_(license_two.builtin, License.OTHER)
|
|
|
|
eq_(license_two.id, license_one.id)
|
|
|
|
|
|
|
|
def test_success_switch_license(self):
|
|
|
|
data = self.formset(builtin=1)
|
|
|
|
r = self.client.post(self.url, data)
|
|
|
|
license_one = self.get_version().license
|
|
|
|
|
|
|
|
data = self.formset(builtin=License.OTHER, text='text', name='name')
|
|
|
|
r = self.client.post(self.url, data)
|
|
|
|
eq_(r.status_code, 302)
|
|
|
|
license_two = self.get_version().license
|
|
|
|
eq_(unicode(license_two.text), 'text')
|
|
|
|
eq_(unicode(license_two.name), 'name')
|
|
|
|
eq_(license_two.builtin, License.OTHER)
|
|
|
|
assert license_one != license_two
|
|
|
|
|
|
|
|
# Make sure the old license wasn't edited.
|
|
|
|
license = License.objects.get(builtin=1)
|
|
|
|
eq_(unicode(license.name), 'bsd')
|
|
|
|
|
|
|
|
data = self.formset(builtin=1)
|
|
|
|
r = self.client.post(self.url, data)
|
|
|
|
eq_(r.status_code, 302)
|
|
|
|
license_three = self.get_version().license
|
|
|
|
eq_(license_three, license_one)
|
|
|
|
|
|
|
|
def test_custom_has_text(self):
|
|
|
|
data = self.formset(builtin=License.OTHER, name='name')
|
|
|
|
r = self.client.post(self.url, data)
|
|
|
|
eq_(r.status_code, 200)
|
|
|
|
self.assertFormError(r, 'license_form', None,
|
|
|
|
'License text is required when choosing Other.')
|
|
|
|
|
|
|
|
def test_custom_has_name(self):
|
|
|
|
data = self.formset(builtin=License.OTHER, text='text')
|
|
|
|
r = self.client.post(self.url, data)
|
|
|
|
eq_(r.status_code, 302)
|
|
|
|
license = self.get_version().license
|
|
|
|
eq_(unicode(license.text), 'text')
|
|
|
|
eq_(unicode(license.name), 'Custom License')
|
|
|
|
eq_(license.builtin, License.OTHER)
|
|
|
|
|
|
|
|
def test_no_version(self):
|
|
|
|
# Make sure nothing bad happens if there's no version.
|
|
|
|
self.addon.update(_current_version=None)
|
|
|
|
Version.objects.all().delete()
|
|
|
|
data = self.formset(builtin=License.OTHER, text='text')
|
|
|
|
r = self.client.post(self.url, data)
|
|
|
|
eq_(r.status_code, 302)
|
|
|
|
|
2010-12-01 20:56:49 +03:00
|
|
|
def test_license_details_links(self):
|
|
|
|
# Check that builtin licenses get details links.
|
|
|
|
doc = pq(unicode(LicenseForm()))
|
|
|
|
for license in License.objects.builtins():
|
|
|
|
radio = 'input.license[value=%s]' % license.builtin
|
|
|
|
eq_(doc(radio).parent().text(), unicode(license.name) + ' Details')
|
|
|
|
eq_(doc(radio + '+ a').attr('href'), license.url)
|
|
|
|
eq_(doc('input[name=builtin]:last-child').parent().text(), 'Other')
|
|
|
|
|
2010-12-10 04:39:52 +03:00
|
|
|
def test_license_logs(self):
|
|
|
|
data = self.formset(builtin=License.OTHER, text='text')
|
|
|
|
self.version.files.all().delete()
|
|
|
|
self.version.addon.update(status=amo.STATUS_PUBLIC)
|
|
|
|
self.client.post(self.url, data)
|
2010-12-27 19:20:55 +03:00
|
|
|
eq_(ActivityLog.objects.all().count(), 2)
|
2010-12-10 04:39:52 +03:00
|
|
|
|
|
|
|
self.version.license = License.objects.all()[1]
|
2010-12-27 19:20:55 +03:00
|
|
|
self.version.save()
|
2010-12-10 04:39:52 +03:00
|
|
|
|
|
|
|
data = self.formset(builtin=License.OTHER, text='text')
|
2010-12-30 20:54:28 +03:00
|
|
|
self.client.post(self.url, data)
|
2010-12-27 19:20:55 +03:00
|
|
|
eq_(ActivityLog.objects.all().count(), 3)
|
2010-12-10 04:39:52 +03:00
|
|
|
|
2010-10-05 23:24:31 +04:00
|
|
|
|
|
|
|
class TestEditAuthor(TestOwnership):
|
|
|
|
|
2010-09-30 07:12:18 +04:00
|
|
|
def test_success_add_user(self):
|
|
|
|
q = (AddonUser.objects.no_cache().filter(addon=3615)
|
|
|
|
.values_list('user', flat=True))
|
|
|
|
eq_(list(q.all()), [55021])
|
|
|
|
|
|
|
|
f = self.client.get(self.url).context['user_form'].initial_forms[0]
|
|
|
|
u = dict(user='regular@mozilla.com', listed=True,
|
2010-10-12 03:06:15 +04:00
|
|
|
role=amo.AUTHOR_ROLE_DEV, position=0)
|
2010-09-30 07:12:18 +04:00
|
|
|
data = self.formset(f.initial, u, initial_count=1)
|
|
|
|
r = self.client.post(self.url, data)
|
|
|
|
eq_(r.status_code, 302)
|
|
|
|
eq_(list(q.all()), [55021, 999])
|
|
|
|
|
|
|
|
def test_success_edit_user(self):
|
|
|
|
# Add an author b/c we can't edit anything about the current one.
|
|
|
|
f = self.client.get(self.url).context['user_form'].initial_forms[0]
|
|
|
|
u = dict(user='regular@mozilla.com', listed=True,
|
2010-10-12 03:06:15 +04:00
|
|
|
role=amo.AUTHOR_ROLE_DEV, position=1)
|
2010-09-30 07:12:18 +04:00
|
|
|
data = self.formset(f.initial, u, initial_count=1)
|
|
|
|
self.client.post(self.url, data)
|
|
|
|
eq_(AddonUser.objects.get(addon=3615, user=999).listed, True)
|
|
|
|
|
|
|
|
# Edit the user we just added.
|
2010-10-13 00:53:05 +04:00
|
|
|
user_form = self.client.get(self.url).context['user_form']
|
|
|
|
one, two = user_form.initial_forms
|
|
|
|
del two.initial['listed']
|
|
|
|
empty = dict(user='', listed=True, role=5, position=0)
|
|
|
|
data = self.formset(one.initial, two.initial, empty, initial_count=2)
|
2010-09-30 07:12:18 +04:00
|
|
|
r = self.client.post(self.url, data)
|
|
|
|
eq_(r.status_code, 302)
|
|
|
|
eq_(AddonUser.objects.no_cache().get(addon=3615, user=999).listed,
|
|
|
|
False)
|
|
|
|
|
2010-10-13 00:53:05 +04:00
|
|
|
def test_add_user_twice(self):
|
|
|
|
f = self.client.get(self.url).context['user_form'].initial_forms[0]
|
|
|
|
u = dict(user='regular@mozilla.com', listed=True,
|
|
|
|
role=amo.AUTHOR_ROLE_DEV, position=1)
|
|
|
|
data = self.formset(f.initial, u, u, initial_count=1)
|
|
|
|
r = self.client.post(self.url, data)
|
|
|
|
eq_(r.status_code, 200)
|
|
|
|
eq_(r.context['user_form'].non_form_errors(),
|
|
|
|
['An author can only be listed once.'])
|
|
|
|
|
2010-09-30 07:12:18 +04:00
|
|
|
def test_success_delete_user(self):
|
2010-10-21 21:05:30 +04:00
|
|
|
# Add a new user so we have one to delete.
|
2010-09-30 07:12:18 +04:00
|
|
|
data = self.formset(dict(user='regular@mozilla.com', listed=True,
|
2010-10-21 21:05:30 +04:00
|
|
|
role=amo.AUTHOR_ROLE_OWNER, position=1),
|
|
|
|
initial_count=0)
|
2010-09-30 07:12:18 +04:00
|
|
|
self.client.post(self.url, data)
|
|
|
|
|
|
|
|
one, two = self.client.get(self.url).context['user_form'].initial_forms
|
|
|
|
one.initial['DELETE'] = True
|
|
|
|
data = self.formset(one.initial, two.initial, initial_count=2)
|
|
|
|
r = self.client.post(self.url, data)
|
|
|
|
eq_(r.status_code, 302)
|
|
|
|
eq_(999, AddonUser.objects.get(addon=3615).user_id)
|
|
|
|
|
2010-11-02 20:45:45 +03:00
|
|
|
def test_logs(self):
|
|
|
|
# A copy of switch ownership to test logs
|
|
|
|
f = self.client.get(self.url).context['user_form'].initial_forms[0]
|
|
|
|
f.initial['user'] = 'regular@mozilla.com'
|
|
|
|
data = self.formset(f.initial, initial_count=1)
|
|
|
|
o = ActivityLog.objects
|
|
|
|
eq_(o.count(), 0)
|
|
|
|
r = self.client.post(self.url, data)
|
|
|
|
eq_(o.filter(action=amo.LOG.CHANGE_USER_WITH_ROLE.id).count(), 1)
|
|
|
|
eq_(r.status_code, 302)
|
|
|
|
eq_(999, AddonUser.objects.get(addon=3615).user_id)
|
|
|
|
|
2010-09-30 07:12:18 +04:00
|
|
|
def test_switch_owner(self):
|
|
|
|
# See if we can transfer ownership in one POST.
|
|
|
|
f = self.client.get(self.url).context['user_form'].initial_forms[0]
|
|
|
|
f.initial['user'] = 'regular@mozilla.com'
|
|
|
|
data = self.formset(f.initial, initial_count=1)
|
|
|
|
r = self.client.post(self.url, data)
|
|
|
|
eq_(r.status_code, 302)
|
|
|
|
eq_(999, AddonUser.objects.get(addon=3615).user_id)
|
|
|
|
|
|
|
|
def test_only_owner_can_edit(self):
|
|
|
|
f = self.client.get(self.url).context['user_form'].initial_forms[0]
|
|
|
|
u = dict(user='regular@mozilla.com', listed=True,
|
2010-10-12 03:06:15 +04:00
|
|
|
role=amo.AUTHOR_ROLE_DEV, position=0)
|
2010-09-30 07:12:18 +04:00
|
|
|
data = self.formset(f.initial, u, initial_count=1)
|
|
|
|
self.client.post(self.url, data)
|
|
|
|
|
|
|
|
self.client.login(username='regular@mozilla.com', password='password')
|
|
|
|
self.client.post(self.url, data, follow=True)
|
|
|
|
|
|
|
|
# Try deleting the other AddonUser
|
|
|
|
one, two = self.client.get(self.url).context['user_form'].initial_forms
|
|
|
|
one.initial['DELETE'] = True
|
|
|
|
data = self.formset(one.initial, two.initial, initial_count=2)
|
|
|
|
r = self.client.post(self.url, data, follow=True)
|
|
|
|
eq_(r.status_code, 403)
|
|
|
|
eq_(AddonUser.objects.filter(addon=3615).count(), 2)
|
|
|
|
|
|
|
|
def test_must_have_listed(self):
|
|
|
|
f = self.client.get(self.url).context['user_form'].initial_forms[0]
|
|
|
|
f.initial['listed'] = False
|
|
|
|
data = self.formset(f.initial, initial_count=1)
|
|
|
|
r = self.client.post(self.url, data)
|
|
|
|
eq_(r.context['user_form'].non_form_errors(),
|
|
|
|
['At least one author must be listed.'])
|
|
|
|
|
|
|
|
def test_must_have_owner(self):
|
|
|
|
f = self.client.get(self.url).context['user_form'].initial_forms[0]
|
|
|
|
f.initial['role'] = amo.AUTHOR_ROLE_DEV
|
|
|
|
data = self.formset(f.initial, initial_count=1)
|
|
|
|
r = self.client.post(self.url, data)
|
|
|
|
eq_(r.context['user_form'].non_form_errors(),
|
|
|
|
['Must have at least one owner.'])
|
|
|
|
|
|
|
|
def test_must_have_owner_delete(self):
|
|
|
|
f = self.client.get(self.url).context['user_form'].initial_forms[0]
|
|
|
|
f.initial['DELETE'] = True
|
|
|
|
data = self.formset(f.initial, initial_count=1)
|
|
|
|
r = self.client.post(self.url, data)
|
|
|
|
eq_(r.context['user_form'].non_form_errors(),
|
|
|
|
['Must have at least one owner.'])
|
2010-10-08 07:08:41 +04:00
|
|
|
|
|
|
|
|
2011-01-03 23:58:15 +03:00
|
|
|
class TestVersionStats(test_utils.TestCase):
|
|
|
|
fixtures = ['base/apps', 'base/users', 'base/addon_3615']
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
assert self.client.login(username='admin@mozilla.com',
|
|
|
|
password='password')
|
|
|
|
|
|
|
|
def test_counts(self):
|
|
|
|
addon = Addon.objects.get(id=3615)
|
|
|
|
version = addon.current_version
|
|
|
|
user = UserProfile.objects.get(email='admin@mozilla.com')
|
|
|
|
for _ in range(10):
|
|
|
|
Review.objects.create(addon=addon, user=user,
|
|
|
|
version=addon.current_version)
|
|
|
|
|
|
|
|
url = reverse('devhub.versions.stats', args=[addon.slug])
|
|
|
|
r = json.loads(self.client.get(url).content)
|
|
|
|
exp = {str(version.id):
|
|
|
|
{'reviews': 10, 'files': 1, 'version': version.version,
|
|
|
|
'id': version.id}}
|
|
|
|
self.assertDictEqual(r, exp)
|
|
|
|
|
|
|
|
|
2010-10-08 07:08:41 +04:00
|
|
|
class TestEditPayments(test_utils.TestCase):
|
|
|
|
fixtures = ['base/apps', 'base/users', 'base/addon_3615']
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
self.addon = self.get_addon()
|
2010-11-03 02:40:33 +03:00
|
|
|
self.addon.the_reason = self.addon.the_future = '...'
|
|
|
|
self.addon.save()
|
2010-10-08 07:08:41 +04:00
|
|
|
self.foundation = Charity.objects.create(
|
|
|
|
id=amo.FOUNDATION_ORG, name='moz', url='$$.moz', paypal='moz.pal')
|
2010-12-20 23:47:01 +03:00
|
|
|
self.url = reverse('devhub.addons.payments', args=[self.addon.slug])
|
2010-10-08 07:08:41 +04:00
|
|
|
assert self.client.login(username='del@icio.us', password='password')
|
2010-10-11 22:24:41 +04:00
|
|
|
self.paypal_mock = mock.Mock()
|
|
|
|
self.paypal_mock.return_value = (True, None)
|
|
|
|
paypal.check_paypal_id = self.paypal_mock
|
2010-10-08 07:08:41 +04:00
|
|
|
|
|
|
|
def get_addon(self):
|
|
|
|
return Addon.objects.no_cache().get(id=3615)
|
|
|
|
|
|
|
|
def post(self, *args, **kw):
|
|
|
|
d = dict(*args, **kw)
|
|
|
|
eq_(self.client.post(self.url, d).status_code, 302)
|
|
|
|
|
|
|
|
def check(self, **kw):
|
|
|
|
addon = self.get_addon()
|
|
|
|
for k, v in kw.items():
|
|
|
|
eq_(getattr(addon, k), v)
|
|
|
|
assert addon.wants_contributions
|
|
|
|
assert addon.takes_contributions
|
|
|
|
|
2010-11-04 23:22:57 +03:00
|
|
|
def test_logging(self):
|
|
|
|
count = ActivityLog.objects.all().count()
|
|
|
|
self.post(recipient='dev', suggested_amount=2, paypal_id='greed@dev',
|
|
|
|
annoying=amo.CONTRIB_AFTER)
|
|
|
|
eq_(ActivityLog.objects.all().count(), count + 1)
|
|
|
|
|
2010-10-08 07:08:41 +04:00
|
|
|
def test_success_dev(self):
|
|
|
|
self.post(recipient='dev', suggested_amount=2, paypal_id='greed@dev',
|
|
|
|
annoying=amo.CONTRIB_AFTER)
|
|
|
|
self.check(paypal_id='greed@dev', suggested_amount=2,
|
|
|
|
annoying=amo.CONTRIB_AFTER)
|
|
|
|
|
|
|
|
def test_success_foundation(self):
|
2010-11-03 02:40:33 +03:00
|
|
|
self.post(recipient='moz', suggested_amount=2,
|
2010-10-08 07:08:41 +04:00
|
|
|
annoying=amo.CONTRIB_ROADBLOCK)
|
2010-11-03 02:40:33 +03:00
|
|
|
self.check(paypal_id='', suggested_amount=2,
|
2010-10-08 07:08:41 +04:00
|
|
|
charity=self.foundation, annoying=amo.CONTRIB_ROADBLOCK)
|
|
|
|
|
|
|
|
def test_success_charity(self):
|
|
|
|
d = dict(recipient='org', suggested_amount=11.5,
|
|
|
|
annoying=amo.CONTRIB_PASSIVE)
|
2010-10-11 22:24:41 +04:00
|
|
|
d.update({'charity-name': 'fligtar fund',
|
|
|
|
'charity-url': 'http://feed.me',
|
2010-10-08 07:08:41 +04:00
|
|
|
'charity-paypal': 'greed@org'})
|
|
|
|
self.post(d)
|
|
|
|
self.check(paypal_id='', suggested_amount=Decimal('11.50'),
|
|
|
|
charity=Charity.objects.get(name='fligtar fund'))
|
|
|
|
|
|
|
|
def test_dev_paypal_reqd(self):
|
|
|
|
d = dict(recipient='dev', suggested_amount=2,
|
|
|
|
annoying=amo.CONTRIB_PASSIVE)
|
|
|
|
r = self.client.post(self.url, d)
|
2010-10-20 23:06:32 +04:00
|
|
|
self.assertFormError(r, 'contrib_form', 'paypal_id',
|
2010-11-30 03:44:25 +03:00
|
|
|
'PayPal ID required to accept contributions.')
|
2010-10-08 07:08:41 +04:00
|
|
|
|
2010-10-11 23:49:14 +04:00
|
|
|
def test_bad_paypal_id_dev(self):
|
2010-10-11 22:24:41 +04:00
|
|
|
self.paypal_mock.return_value = False, 'error'
|
|
|
|
d = dict(recipient='dev', suggested_amount=2, paypal_id='greed@dev',
|
|
|
|
annoying=amo.CONTRIB_AFTER)
|
|
|
|
r = self.client.post(self.url, d)
|
2010-10-20 23:06:32 +04:00
|
|
|
self.assertFormError(r, 'contrib_form', 'paypal_id', 'error')
|
2010-10-11 23:49:14 +04:00
|
|
|
|
|
|
|
def test_bad_paypal_id_charity(self):
|
|
|
|
self.paypal_mock.return_value = False, 'error'
|
|
|
|
d = dict(recipient='org', suggested_amount=11.5,
|
|
|
|
annoying=amo.CONTRIB_PASSIVE)
|
|
|
|
d.update({'charity-name': 'fligtar fund',
|
|
|
|
'charity-url': 'http://feed.me',
|
|
|
|
'charity-paypal': 'greed@org'})
|
|
|
|
r = self.client.post(self.url, d)
|
|
|
|
self.assertFormError(r, 'charity_form', 'paypal', 'error')
|
2010-10-11 22:24:41 +04:00
|
|
|
|
|
|
|
def test_paypal_timeout(self):
|
|
|
|
self.paypal_mock.side_effect = socket.timeout()
|
|
|
|
d = dict(recipient='dev', suggested_amount=2, paypal_id='greed@dev',
|
|
|
|
annoying=amo.CONTRIB_AFTER)
|
|
|
|
r = self.client.post(self.url, d)
|
2010-10-20 23:06:32 +04:00
|
|
|
self.assertFormError(r, 'contrib_form', 'paypal_id',
|
2010-10-11 22:24:41 +04:00
|
|
|
'Could not validate PayPal id.')
|
|
|
|
|
2010-10-31 08:24:20 +03:00
|
|
|
def test_max_suggested_amount(self):
|
|
|
|
too_much = settings.MAX_CONTRIBUTION + 1
|
|
|
|
msg = ('Please enter a suggested amount less than $%d.' %
|
|
|
|
settings.MAX_CONTRIBUTION)
|
|
|
|
r = self.client.post(self.url, {'suggested_amount': too_much})
|
|
|
|
self.assertFormError(r, 'contrib_form', 'suggested_amount', msg)
|
|
|
|
|
2010-12-24 01:41:33 +03:00
|
|
|
def test_neg_suggested_amount(self):
|
|
|
|
msg = 'Please enter a suggested amount greater than 0.'
|
|
|
|
r = self.client.post(self.url, {'suggested_amount': -1})
|
|
|
|
self.assertFormError(r, 'contrib_form', 'suggested_amount', msg)
|
|
|
|
|
2010-10-08 07:08:41 +04:00
|
|
|
def test_charity_details_reqd(self):
|
|
|
|
d = dict(recipient='org', suggested_amount=11.5,
|
|
|
|
annoying=amo.CONTRIB_PASSIVE)
|
|
|
|
r = self.client.post(self.url, d)
|
|
|
|
self.assertFormError(r, 'charity_form', 'name',
|
|
|
|
'This field is required.')
|
|
|
|
eq_(self.get_addon().suggested_amount, None)
|
|
|
|
|
|
|
|
def test_switch_charity_to_dev(self):
|
|
|
|
self.test_success_charity()
|
|
|
|
self.test_success_dev()
|
|
|
|
eq_(self.get_addon().charity, None)
|
|
|
|
eq_(self.get_addon().charity_id, None)
|
|
|
|
|
|
|
|
def test_switch_charity_to_foundation(self):
|
|
|
|
self.test_success_charity()
|
|
|
|
self.test_success_foundation()
|
|
|
|
# This will break if we start cleaning up licenses.
|
|
|
|
old_charity = Charity.objects.get(name='fligtar fund')
|
|
|
|
assert old_charity.id != self.foundation
|
|
|
|
|
|
|
|
def test_switch_foundation_to_charity(self):
|
|
|
|
self.test_success_foundation()
|
|
|
|
self.test_success_charity()
|
|
|
|
moz = Charity.objects.get(id=self.foundation.id)
|
|
|
|
eq_(moz.name, 'moz')
|
|
|
|
eq_(moz.url, '$$.moz')
|
|
|
|
eq_(moz.paypal, 'moz.pal')
|
|
|
|
|
|
|
|
def test_contrib_form_initial(self):
|
|
|
|
eq_(ContribForm.initial(self.addon)['recipient'], 'dev')
|
|
|
|
self.addon.charity = self.foundation
|
|
|
|
eq_(ContribForm.initial(self.addon)['recipient'], 'moz')
|
|
|
|
self.addon.charity_id = amo.FOUNDATION_ORG + 1
|
|
|
|
eq_(ContribForm.initial(self.addon)['recipient'], 'org')
|
|
|
|
|
|
|
|
eq_(ContribForm.initial(self.addon)['annoying'], amo.CONTRIB_PASSIVE)
|
|
|
|
self.addon.annoying = amo.CONTRIB_AFTER
|
|
|
|
eq_(ContribForm.initial(self.addon)['annoying'], amo.CONTRIB_AFTER)
|
2010-10-12 21:51:17 +04:00
|
|
|
|
2010-11-01 23:23:25 +03:00
|
|
|
def test_enable_thankyou(self):
|
|
|
|
d = dict(enable_thankyou='on', thankyou_note='woo',
|
|
|
|
annoying=1, recipient='moz')
|
|
|
|
r = self.client.post(self.url, d)
|
|
|
|
eq_(r.status_code, 302)
|
|
|
|
addon = self.get_addon()
|
|
|
|
eq_(addon.enable_thankyou, True)
|
|
|
|
eq_(unicode(addon.thankyou_note), 'woo')
|
|
|
|
|
|
|
|
def test_enable_thankyou_unchecked_with_text(self):
|
|
|
|
d = dict(enable_thankyou='', thankyou_note='woo',
|
|
|
|
annoying=1, recipient='moz')
|
|
|
|
r = self.client.post(self.url, d)
|
|
|
|
eq_(r.status_code, 302)
|
|
|
|
addon = self.get_addon()
|
|
|
|
eq_(addon.enable_thankyou, False)
|
|
|
|
eq_(addon.thankyou_note, None)
|
|
|
|
|
|
|
|
def test_enable_thankyou_no_text(self):
|
|
|
|
d = dict(enable_thankyou='on', thankyou_note='',
|
|
|
|
annoying=1, recipient='moz')
|
|
|
|
r = self.client.post(self.url, d)
|
|
|
|
eq_(r.status_code, 302)
|
|
|
|
addon = self.get_addon()
|
|
|
|
eq_(addon.enable_thankyou, False)
|
|
|
|
eq_(addon.thankyou_note, None)
|
|
|
|
|
2010-12-29 21:22:15 +03:00
|
|
|
def test_require_public_status_to_edit(self):
|
|
|
|
# pyquery drops all the attributes on <body> so we just go
|
|
|
|
# for string search.
|
2010-12-30 00:33:47 +03:00
|
|
|
assert 'no-edit' not in self.client.get(self.url).content
|
2010-12-29 21:22:15 +03:00
|
|
|
self.get_addon().update(status=amo.STATUS_LITE)
|
2010-12-30 00:33:47 +03:00
|
|
|
assert 'no-edit' in self.client.get(self.url).content
|
2010-12-29 21:22:15 +03:00
|
|
|
|
2010-10-12 21:51:17 +04:00
|
|
|
|
|
|
|
class TestDisablePayments(test_utils.TestCase):
|
|
|
|
fixtures = ['base/apps', 'base/users', 'base/addon_3615']
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
self.addon = Addon.objects.get(id=3615)
|
2010-11-03 02:40:33 +03:00
|
|
|
self.addon.the_reason = self.addon.the_future = '...'
|
|
|
|
self.addon.save()
|
2010-10-12 21:51:17 +04:00
|
|
|
self.addon.update(wants_contributions=True, paypal_id='woohoo')
|
2010-12-20 23:47:01 +03:00
|
|
|
self.pay_url = reverse('devhub.addons.payments',
|
|
|
|
args=[self.addon.slug])
|
2010-10-12 21:51:17 +04:00
|
|
|
self.disable_url = reverse('devhub.addons.payments.disable',
|
2010-12-20 23:47:01 +03:00
|
|
|
args=[self.addon.slug])
|
2010-10-12 21:51:17 +04:00
|
|
|
assert self.client.login(username='del@icio.us', password='password')
|
|
|
|
|
|
|
|
def test_statusbar_visible(self):
|
|
|
|
r = self.client.get(self.pay_url)
|
|
|
|
self.assertContains(r, '<div id="status-bar">')
|
|
|
|
|
|
|
|
self.addon.update(wants_contributions=False)
|
|
|
|
r = self.client.get(self.pay_url)
|
|
|
|
self.assertNotContains(r, '<div id="status-bar">')
|
|
|
|
|
|
|
|
def test_disable(self):
|
|
|
|
r = self.client.post(self.disable_url)
|
|
|
|
eq_(r.status_code, 302)
|
|
|
|
assert(r['Location'].endswith(self.pay_url))
|
|
|
|
eq_(Addon.uncached.get(id=3615).wants_contributions, False)
|
2010-10-13 20:14:01 +04:00
|
|
|
|
|
|
|
|
2010-11-03 02:40:33 +03:00
|
|
|
class TestPaymentsProfile(test_utils.TestCase):
|
|
|
|
fixtures = ['base/apps', 'base/users', 'base/addon_3615']
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
self.addon = a = self.get_addon()
|
2010-12-20 23:47:01 +03:00
|
|
|
self.url = reverse('devhub.addons.payments', args=[self.addon.slug])
|
2010-11-03 02:40:33 +03:00
|
|
|
# Make sure all the payment/profile data is clear.
|
|
|
|
assert not (a.wants_contributions or a.paypal_id or a.the_reason
|
|
|
|
or a.the_future or a.takes_contributions)
|
|
|
|
assert self.client.login(username='del@icio.us', password='password')
|
|
|
|
self.paypal_mock = mock.Mock()
|
|
|
|
self.paypal_mock.return_value = (True, None)
|
|
|
|
paypal.check_paypal_id = self.paypal_mock
|
|
|
|
|
|
|
|
def get_addon(self):
|
|
|
|
return Addon.objects.get(id=3615)
|
|
|
|
|
|
|
|
def test_intro_box(self):
|
|
|
|
# We don't have payments/profile set up, so we see the intro.
|
|
|
|
doc = pq(self.client.get(self.url).content)
|
|
|
|
assert doc('.intro')
|
|
|
|
assert doc('#setup.hidden')
|
|
|
|
|
|
|
|
def test_status_bar(self):
|
|
|
|
# We don't have payments/profile set up, so no status bar.
|
|
|
|
doc = pq(self.client.get(self.url).content)
|
|
|
|
assert not doc('#status-bar')
|
|
|
|
|
|
|
|
def test_profile_form_exists(self):
|
|
|
|
doc = pq(self.client.get(self.url).content)
|
2010-11-30 02:31:53 +03:00
|
|
|
assert doc('#trans-the_reason')
|
|
|
|
assert doc('#trans-the_future')
|
2010-11-03 02:40:33 +03:00
|
|
|
|
|
|
|
def test_profile_form_success(self):
|
|
|
|
d = dict(recipient='dev', suggested_amount=2, paypal_id='xx@yy',
|
|
|
|
annoying=amo.CONTRIB_ROADBLOCK, the_reason='xxx',
|
|
|
|
the_future='yyy')
|
|
|
|
r = self.client.post(self.url, d)
|
|
|
|
eq_(r.status_code, 302)
|
|
|
|
|
|
|
|
# The profile form is gone, we're accepting contributions.
|
|
|
|
doc = pq(self.client.get(self.url).content)
|
|
|
|
assert not doc('.intro')
|
|
|
|
assert not doc('#setup.hidden')
|
|
|
|
assert doc('#status-bar')
|
2010-11-30 02:31:53 +03:00
|
|
|
assert not doc('#trans-the_reason')
|
|
|
|
assert not doc('#trans-the_future')
|
2010-11-03 02:40:33 +03:00
|
|
|
|
|
|
|
addon = self.get_addon()
|
|
|
|
eq_(unicode(addon.the_reason), 'xxx')
|
|
|
|
eq_(unicode(addon.the_future), 'yyy')
|
|
|
|
eq_(addon.wants_contributions, True)
|
|
|
|
|
|
|
|
def test_profile_required(self):
|
|
|
|
def check_page(request):
|
|
|
|
doc = pq(request.content)
|
|
|
|
assert not doc('.intro')
|
|
|
|
assert not doc('#setup.hidden')
|
|
|
|
assert not doc('#status-bar')
|
2010-11-30 02:31:53 +03:00
|
|
|
assert doc('#trans-the_reason')
|
|
|
|
assert doc('#trans-the_future')
|
2010-11-03 02:40:33 +03:00
|
|
|
|
|
|
|
d = dict(recipient='dev', suggested_amount=2, paypal_id='xx@yy',
|
|
|
|
annoying=amo.CONTRIB_ROADBLOCK)
|
|
|
|
r = self.client.post(self.url, d)
|
|
|
|
eq_(r.status_code, 200)
|
|
|
|
self.assertFormError(r, 'profile_form', 'the_reason',
|
|
|
|
'This field is required.')
|
|
|
|
self.assertFormError(r, 'profile_form', 'the_future',
|
|
|
|
'This field is required.')
|
|
|
|
check_page(r)
|
|
|
|
eq_(self.get_addon().wants_contributions, False)
|
|
|
|
|
|
|
|
d = dict(recipient='dev', suggested_amount=2, paypal_id='xx@yy',
|
|
|
|
annoying=amo.CONTRIB_ROADBLOCK, the_reason='xxx')
|
|
|
|
r = self.client.post(self.url, d)
|
|
|
|
eq_(r.status_code, 200)
|
|
|
|
self.assertFormError(r, 'profile_form', 'the_future',
|
|
|
|
'This field is required.')
|
|
|
|
check_page(r)
|
|
|
|
eq_(self.get_addon().wants_contributions, False)
|
|
|
|
|
|
|
|
|
2010-11-15 21:56:20 +03:00
|
|
|
class TestDelete(test_utils.TestCase):
|
|
|
|
fixtures = ('base/apps', 'base/users', 'base/addon_3615',
|
|
|
|
'base/addon_5579',)
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
self.addon = self.get_addon()
|
|
|
|
assert self.client.login(username='del@icio.us', password='password')
|
2010-12-20 23:47:01 +03:00
|
|
|
self.url = reverse('devhub.addons.delete', args=[self.addon.slug])
|
2010-11-15 21:56:20 +03:00
|
|
|
|
|
|
|
def get_addon(self):
|
|
|
|
return Addon.objects.no_cache().get(id=3615)
|
|
|
|
|
|
|
|
def test_post_nopw(self):
|
|
|
|
r = self.client.post(self.url, follow=True)
|
|
|
|
eq_(pq(r.content)('.notification-box').text(),
|
|
|
|
'Password was incorrect. Add-on was not deleted.')
|
|
|
|
|
|
|
|
def test_post(self):
|
|
|
|
r = self.client.post(self.url, dict(password='password'), follow=True)
|
|
|
|
eq_(pq(r.content)('.notification-box').text(), 'Add-on deleted.')
|
|
|
|
self.assertRaises(Addon.DoesNotExist, self.get_addon)
|
|
|
|
|
|
|
|
|
2010-10-13 20:14:01 +04:00
|
|
|
class TestEdit(test_utils.TestCase):
|
2010-11-30 02:36:13 +03:00
|
|
|
fixtures = ('base/apps', 'base/users', 'base/addon_3615',
|
2010-12-21 03:51:09 +03:00
|
|
|
'base/addon_5579', 'base/addon_3615_categories')
|
2010-10-13 20:14:01 +04:00
|
|
|
|
|
|
|
def setUp(self):
|
2010-10-15 08:12:56 +04:00
|
|
|
super(TestEdit, self).setUp()
|
2010-12-10 06:51:46 +03:00
|
|
|
addon = self.get_addon()
|
2010-10-13 20:14:01 +04:00
|
|
|
assert self.client.login(username='del@icio.us', password='password')
|
2010-12-20 23:47:01 +03:00
|
|
|
self.url = reverse('devhub.addons.edit', args=[addon.slug])
|
2010-11-11 22:33:39 +03:00
|
|
|
self.user = UserProfile.objects.get(pk=55021)
|
|
|
|
|
2010-12-10 06:51:46 +03:00
|
|
|
AddonCategory.objects.filter(addon=addon,
|
|
|
|
category=Category.objects.get(id=23)).delete()
|
|
|
|
AddonCategory.objects.filter(addon=addon,
|
|
|
|
category=Category.objects.get(id=24)).delete()
|
|
|
|
|
2010-11-11 22:33:39 +03:00
|
|
|
self.tags = ['tag3', 'tag2', 'tag1']
|
|
|
|
for t in self.tags:
|
2010-12-10 06:51:46 +03:00
|
|
|
Tag(tag_text=t).save_tag(addon, self.user)
|
2010-11-23 06:03:07 +03:00
|
|
|
self._redis = mock_redis()
|
|
|
|
|
2010-12-10 06:51:46 +03:00
|
|
|
self.addon = self.get_addon()
|
|
|
|
|
2011-01-05 01:26:30 +03:00
|
|
|
self.old_settings = {
|
|
|
|
'preview': settings.PREVIEW_THUMBNAIL_PATH,
|
2011-01-18 13:53:22 +03:00
|
|
|
'icons': settings.ADDON_ICONS_PATH,
|
2011-01-05 01:26:30 +03:00
|
|
|
}
|
|
|
|
settings.PREVIEW_THUMBNAIL_PATH = tempfile.mkstemp()[1] + '%s/%d.png'
|
|
|
|
settings.ADDON_ICONS_PATH = tempfile.mkdtemp()
|
|
|
|
|
2011-01-06 23:36:36 +03:00
|
|
|
self.basic_url = self.get_url('basic', True)
|
|
|
|
ctx = self.client.get(self.basic_url).context['cat_form']
|
|
|
|
self.cat_initial = initial(ctx.initial_forms[0])
|
2011-01-12 02:53:58 +03:00
|
|
|
self.preview_upload = reverse('devhub.addons.upload_preview',
|
|
|
|
args=[self.addon.slug])
|
|
|
|
self.icon_upload = reverse('devhub.addons.upload_icon',
|
|
|
|
args=[self.addon.slug])
|
2011-01-06 23:36:36 +03:00
|
|
|
|
2011-01-05 01:26:30 +03:00
|
|
|
def tearDown(self):
|
|
|
|
reset_redis(self._redis)
|
|
|
|
settings.PREVIEW_THUMBNAIL_PATH = self.old_settings['preview']
|
|
|
|
settings.ADDON_ICONS_PATH = self.old_settings['icons']
|
|
|
|
|
2010-12-31 04:02:31 +03:00
|
|
|
def formset_new_form(self, *args, **kw):
|
|
|
|
ctx = self.client.get(self.get_url('media', True)).context
|
|
|
|
|
|
|
|
blank = initial(ctx['preview_form'].forms[-1])
|
|
|
|
blank.update(**kw)
|
|
|
|
return blank
|
|
|
|
|
|
|
|
def formset_media(self, *args, **kw):
|
|
|
|
kw.setdefault('initial_count', 0)
|
|
|
|
kw.setdefault('prefix', 'files')
|
|
|
|
|
|
|
|
fs = formset(*[a for a in args] + [self.formset_new_form()], **kw)
|
|
|
|
return dict([(k, '' if v is None else v) for k, v in fs.items()])
|
|
|
|
|
2010-10-15 08:12:56 +04:00
|
|
|
def get_addon(self):
|
|
|
|
return Addon.objects.no_cache().get(id=3615)
|
2010-10-13 20:14:01 +04:00
|
|
|
|
2010-10-18 21:57:48 +04:00
|
|
|
def get_url(self, section, edit=False):
|
2010-12-20 23:47:01 +03:00
|
|
|
args = [self.addon.slug, section]
|
2010-10-18 21:57:48 +04:00
|
|
|
if edit:
|
|
|
|
args.append('edit')
|
|
|
|
return reverse('devhub.addons.section', args=args)
|
|
|
|
|
2010-10-13 20:14:01 +04:00
|
|
|
def test_redirect(self):
|
|
|
|
# /addon/:id => /addon/:id/edit
|
|
|
|
r = self.client.get('/en-US/developers/addon/3615/', follow=True)
|
2010-12-20 23:47:01 +03:00
|
|
|
url = reverse('devhub.addons.edit', args=['a3615'])
|
2010-10-13 20:14:01 +04:00
|
|
|
self.assertRedirects(r, url, 301)
|
2010-10-11 02:51:45 +04:00
|
|
|
|
2011-01-06 22:55:03 +03:00
|
|
|
def get_dict(self, **kw):
|
2011-01-06 23:36:36 +03:00
|
|
|
fs = formset(self.cat_initial, initial_count=1)
|
2011-01-06 22:55:03 +03:00
|
|
|
result = {'name': 'new name', 'slug': 'test_slug',
|
2011-01-06 23:36:36 +03:00
|
|
|
'summary': 'new summary',
|
2011-01-06 22:55:03 +03:00
|
|
|
'tags': ', '.join(self.tags)}
|
|
|
|
result.update(**kw)
|
2011-01-06 23:36:36 +03:00
|
|
|
result.update(fs)
|
2011-01-06 22:55:03 +03:00
|
|
|
return result
|
|
|
|
|
2010-10-15 08:12:56 +04:00
|
|
|
def test_edit_basic(self):
|
|
|
|
old_name = self.addon.name
|
2011-01-06 22:55:03 +03:00
|
|
|
data = self.get_dict()
|
2010-10-15 08:12:56 +04:00
|
|
|
|
2010-10-18 21:57:48 +04:00
|
|
|
r = self.client.post(self.get_url('basic', True), data)
|
2010-10-15 08:12:56 +04:00
|
|
|
eq_(r.status_code, 200)
|
|
|
|
addon = self.get_addon()
|
|
|
|
|
|
|
|
eq_(unicode(addon.name), data['name'])
|
|
|
|
eq_(addon.name.id, old_name.id)
|
|
|
|
|
|
|
|
eq_(unicode(addon.slug), data['slug'])
|
|
|
|
eq_(unicode(addon.summary), data['summary'])
|
|
|
|
|
2010-12-31 07:50:48 +03:00
|
|
|
eq_([unicode(t) for t in addon.tags.all()], sorted(self.tags))
|
2010-11-11 22:33:39 +03:00
|
|
|
|
2011-02-01 04:00:00 +03:00
|
|
|
def test_edit_basic_check_description(self):
|
|
|
|
# Make sure bug 629779 doesn't return.
|
|
|
|
old_desc = self.addon.description
|
|
|
|
data = self.get_dict()
|
|
|
|
|
|
|
|
r = self.client.post(self.get_url('basic', True), data)
|
|
|
|
eq_(r.status_code, 200)
|
|
|
|
addon = self.get_addon()
|
|
|
|
|
|
|
|
eq_(addon.description, old_desc)
|
|
|
|
|
2011-01-18 13:43:04 +03:00
|
|
|
def test_edit_slug_invalid(self):
|
|
|
|
old_edit = self.get_url('basic', True)
|
|
|
|
data = self.get_dict(name='', slug='invalid')
|
|
|
|
r = self.client.post(self.get_url('basic', True), data)
|
|
|
|
doc = pq(r.content)
|
|
|
|
eq_(doc('form').attr('action'), old_edit)
|
|
|
|
|
|
|
|
def test_edit_slug_valid(self):
|
|
|
|
old_edit = self.get_url('basic', True)
|
|
|
|
data = self.get_dict(slug='valid')
|
|
|
|
r = self.client.post(self.get_url('basic', True), data)
|
|
|
|
doc = pq(r.content)
|
|
|
|
assert doc('form').attr('action') != old_edit
|
|
|
|
|
2011-01-11 02:33:34 +03:00
|
|
|
def test_edit_summary_escaping(self):
|
|
|
|
data = self.get_dict()
|
|
|
|
data['summary'] = '<b>oh my</b>'
|
|
|
|
r = self.client.post(self.get_url('basic', True), data)
|
|
|
|
eq_(r.status_code, 200)
|
|
|
|
|
|
|
|
# Fetch the page so the LinkifiedTranslation gets in cache.
|
|
|
|
r = self.client.get(reverse('devhub.addons.edit', args=[data['slug']]))
|
|
|
|
eq_(pq(r.content)('[data-name=summary]').html().strip(),
|
|
|
|
'<span lang="en-us"><b>oh my</b></span>')
|
|
|
|
|
|
|
|
# Now make sure we don't have escaped content in the rendered form.
|
|
|
|
form = AddonFormBasic(instance=self.get_addon(), request=object())
|
|
|
|
eq_(pq('<body>%s</body>' % form['summary'])('[lang="en-us"]').html(),
|
|
|
|
'<b>oh my</b>')
|
|
|
|
|
2011-01-08 00:11:26 +03:00
|
|
|
def test_edit_basic_as_developer(self):
|
|
|
|
self.client.login(username='regular@mozilla.com', password='password')
|
|
|
|
data = self.get_dict()
|
|
|
|
r = self.client.post(self.get_url('basic', True), data)
|
|
|
|
# Make sure we get errors when they are just regular users.
|
|
|
|
eq_(r.status_code, 403)
|
|
|
|
|
|
|
|
devuser = UserProfile.objects.get(pk=999)
|
|
|
|
AddonUser.objects.create(addon=self.get_addon(), user=devuser,
|
|
|
|
role=amo.AUTHOR_ROLE_DEV)
|
|
|
|
r = self.client.post(self.get_url('basic', True), data)
|
|
|
|
|
|
|
|
eq_(r.status_code, 200)
|
|
|
|
addon = self.get_addon()
|
|
|
|
|
|
|
|
eq_(unicode(addon.name), data['name'])
|
|
|
|
|
|
|
|
eq_(unicode(addon.slug), data['slug'])
|
|
|
|
eq_(unicode(addon.summary), data['summary'])
|
|
|
|
|
|
|
|
eq_([unicode(t) for t in addon.tags.all()], sorted(self.tags))
|
|
|
|
|
2010-12-31 09:36:31 +03:00
|
|
|
def test_edit_basic_name_required(self):
|
2011-01-06 22:55:03 +03:00
|
|
|
data = self.get_dict(name='', slug='test_addon')
|
2010-12-31 09:36:31 +03:00
|
|
|
r = self.client.post(self.get_url('basic', True), data)
|
|
|
|
eq_(r.status_code, 200)
|
|
|
|
self.assertFormError(r, 'form', 'name', 'This field is required.')
|
|
|
|
|
|
|
|
def test_edit_basic_name_spaces(self):
|
2011-01-06 22:55:03 +03:00
|
|
|
data = self.get_dict(name=' ', slug='test_addon')
|
2010-12-31 09:36:31 +03:00
|
|
|
r = self.client.post(self.get_url('basic', True), data)
|
|
|
|
eq_(r.status_code, 200)
|
|
|
|
self.assertFormError(r, 'form', 'name', 'This field is required.')
|
|
|
|
|
2010-10-15 08:12:56 +04:00
|
|
|
def test_edit_basic_slugs_unique(self):
|
|
|
|
Addon.objects.get(id=5579).update(slug='test_slug')
|
2011-01-06 22:55:03 +03:00
|
|
|
data = self.get_dict()
|
2010-10-18 21:57:48 +04:00
|
|
|
r = self.client.post(self.get_url('basic', True), data)
|
2010-10-15 08:12:56 +04:00
|
|
|
eq_(r.status_code, 200)
|
|
|
|
self.assertFormError(r, 'form', 'slug', 'This slug is already in use.')
|
|
|
|
|
2010-11-11 22:33:39 +03:00
|
|
|
def test_edit_basic_add_tag(self):
|
|
|
|
count = ActivityLog.objects.all().count()
|
|
|
|
self.tags.insert(0, 'tag4')
|
2011-01-06 22:55:03 +03:00
|
|
|
data = self.get_dict()
|
2010-11-11 22:33:39 +03:00
|
|
|
r = self.client.post(self.get_url('basic', True), data)
|
|
|
|
eq_(r.status_code, 200)
|
|
|
|
|
2010-12-04 00:02:16 +03:00
|
|
|
result = pq(r.content)('#addon_tags_edit').eq(0).text()
|
2010-11-11 22:33:39 +03:00
|
|
|
|
2010-12-31 07:50:48 +03:00
|
|
|
eq_(result, ', '.join(sorted(self.tags)))
|
2010-11-18 03:49:53 +03:00
|
|
|
eq_((ActivityLog.objects.for_addons(self.addon)
|
|
|
|
.get(action=amo.LOG.ADD_TAG.id)).to_string(),
|
|
|
|
'<a href="/en-US/firefox/tag/tag4">tag4</a> added to '
|
2010-12-20 23:47:01 +03:00
|
|
|
'<a href="/en-US/firefox/addon/test_slug/">new name</a>.')
|
2010-11-11 22:33:39 +03:00
|
|
|
eq_(ActivityLog.objects.filter(action=amo.LOG.ADD_TAG.id).count(),
|
|
|
|
count + 1)
|
|
|
|
|
2010-12-11 02:19:10 +03:00
|
|
|
def test_edit_basic_blacklisted_tag(self):
|
2011-01-06 22:55:03 +03:00
|
|
|
Tag.objects.get_or_create(tag_text='blue', blacklisted=True)
|
|
|
|
data = self.get_dict(tags='blue')
|
2010-12-11 02:19:10 +03:00
|
|
|
r = self.client.post(self.get_url('basic', True), data)
|
|
|
|
eq_(r.status_code, 200)
|
|
|
|
|
2011-01-13 05:27:13 +03:00
|
|
|
error = 'Invalid tag: blue'
|
2010-12-31 07:50:48 +03:00
|
|
|
self.assertFormError(r, 'form', 'tags', error)
|
|
|
|
|
|
|
|
def test_edit_basic_blacklisted_tags_2(self):
|
2011-01-06 22:55:03 +03:00
|
|
|
Tag.objects.get_or_create(tag_text='blue', blacklisted=True)
|
2010-12-31 07:50:48 +03:00
|
|
|
Tag.objects.get_or_create(tag_text='darn', blacklisted=True)
|
2011-01-06 22:55:03 +03:00
|
|
|
data = self.get_dict(tags='blue, darn, swearword')
|
2010-12-31 07:50:48 +03:00
|
|
|
r = self.client.post(self.get_url('basic', True), data)
|
|
|
|
eq_(r.status_code, 200)
|
|
|
|
|
2011-01-13 05:27:13 +03:00
|
|
|
error = 'Invalid tags: blue, darn'
|
2010-12-31 07:50:48 +03:00
|
|
|
self.assertFormError(r, 'form', 'tags', error)
|
|
|
|
|
|
|
|
def test_edit_basic_blacklisted_tags_3(self):
|
2011-01-06 22:55:03 +03:00
|
|
|
Tag.objects.get_or_create(tag_text='blue', blacklisted=True)
|
2010-12-31 07:50:48 +03:00
|
|
|
Tag.objects.get_or_create(tag_text='darn', blacklisted=True)
|
|
|
|
Tag.objects.get_or_create(tag_text='swearword', blacklisted=True)
|
2011-01-06 22:55:03 +03:00
|
|
|
data = self.get_dict(tags='blue, darn, swearword')
|
2010-12-31 07:50:48 +03:00
|
|
|
r = self.client.post(self.get_url('basic', True), data)
|
|
|
|
eq_(r.status_code, 200)
|
|
|
|
|
2011-01-13 05:27:13 +03:00
|
|
|
error = 'Invalid tags: blue, darn, swearword'
|
2010-12-11 02:19:10 +03:00
|
|
|
self.assertFormError(r, 'form', 'tags', error)
|
|
|
|
|
2010-11-11 22:33:39 +03:00
|
|
|
def test_edit_basic_remove_tag(self):
|
|
|
|
self.tags.remove('tag2')
|
|
|
|
|
|
|
|
count = ActivityLog.objects.all().count()
|
2011-01-06 22:55:03 +03:00
|
|
|
data = self.get_dict()
|
2010-11-11 22:33:39 +03:00
|
|
|
r = self.client.post(self.get_url('basic', True), data)
|
|
|
|
eq_(r.status_code, 200)
|
2010-10-15 08:12:56 +04:00
|
|
|
|
2010-12-04 00:02:16 +03:00
|
|
|
result = pq(r.content)('#addon_tags_edit').eq(0).text()
|
2010-11-11 22:33:39 +03:00
|
|
|
|
2010-12-31 07:50:48 +03:00
|
|
|
eq_(result, ', '.join(sorted(self.tags)))
|
2010-11-11 22:33:39 +03:00
|
|
|
|
|
|
|
eq_(ActivityLog.objects.filter(action=amo.LOG.REMOVE_TAG.id).count(),
|
|
|
|
count + 1)
|
|
|
|
|
|
|
|
def test_edit_basic_minlength_tags(self):
|
|
|
|
tags = self.tags
|
|
|
|
tags.append('a' * (amo.MIN_TAG_LENGTH - 1))
|
2011-01-06 22:55:03 +03:00
|
|
|
data = self.get_dict()
|
2010-11-11 22:33:39 +03:00
|
|
|
r = self.client.post(self.get_url('basic', True), data)
|
|
|
|
eq_(r.status_code, 200)
|
|
|
|
|
|
|
|
self.assertFormError(r, 'form', 'tags',
|
|
|
|
'All tags must be at least %d characters.' %
|
|
|
|
amo.MIN_TAG_LENGTH)
|
|
|
|
|
|
|
|
def test_edit_basic_max_tags(self):
|
|
|
|
tags = self.tags
|
|
|
|
|
|
|
|
for i in range(amo.MAX_TAGS + 1):
|
|
|
|
tags.append('test%d' % i)
|
|
|
|
|
2011-01-06 22:55:03 +03:00
|
|
|
data = self.get_dict()
|
2010-11-11 22:33:39 +03:00
|
|
|
r = self.client.post(self.get_url('basic', True), data)
|
|
|
|
self.assertFormError(r, 'form', 'tags', 'You have %d too many tags.' %
|
|
|
|
(len(tags) - amo.MAX_TAGS))
|
|
|
|
|
2011-01-06 22:55:03 +03:00
|
|
|
def test_edit_tag_empty_after_slug(self):
|
|
|
|
start = Tag.objects.all().count()
|
|
|
|
data = self.get_dict(tags='>>')
|
|
|
|
self.client.post(self.get_url('basic', True), data)
|
2010-12-10 06:51:46 +03:00
|
|
|
|
2011-01-06 22:55:03 +03:00
|
|
|
# Check that the tag did not get created.
|
|
|
|
eq_(start, Tag.objects.all().count())
|
2010-12-10 06:51:46 +03:00
|
|
|
|
2011-01-06 22:55:03 +03:00
|
|
|
def test_edit_tag_slugified(self):
|
|
|
|
data = self.get_dict(tags='<script>alert("foo")</script>')
|
|
|
|
self.client.post(self.get_url('basic', True), data)
|
|
|
|
tag = Tag.objects.all().order_by('-pk')[0]
|
|
|
|
eq_(tag.tag_text, 'scriptalertfooscript')
|
|
|
|
|
|
|
|
def test_edit_basic_categories_add(self):
|
2011-01-06 23:36:36 +03:00
|
|
|
eq_([c.id for c in self.get_addon().all_categories], [22])
|
|
|
|
self.cat_initial['categories'] = [22, 23]
|
2011-01-13 01:27:31 +03:00
|
|
|
|
2011-01-18 13:53:22 +03:00
|
|
|
self.client.post(self.basic_url, self.get_dict())
|
2011-01-13 01:27:31 +03:00
|
|
|
|
|
|
|
addon_cats = self.get_addon().categories.values_list('id', flat=True)
|
|
|
|
eq_(sorted(addon_cats), [22, 23])
|
2010-12-10 06:51:46 +03:00
|
|
|
|
|
|
|
def test_edit_basic_categories_addandremove(self):
|
|
|
|
AddonCategory(addon=self.addon, category_id=23).save()
|
2011-01-06 23:36:36 +03:00
|
|
|
eq_([c.id for c in self.get_addon().all_categories], [22, 23])
|
2010-12-10 06:51:46 +03:00
|
|
|
|
2011-01-06 23:36:36 +03:00
|
|
|
self.cat_initial['categories'] = [22, 24]
|
2011-01-18 13:53:22 +03:00
|
|
|
self.client.post(self.basic_url, self.get_dict())
|
2010-12-10 06:51:46 +03:00
|
|
|
|
2011-01-13 01:27:31 +03:00
|
|
|
addon_cats = self.get_addon().categories.values_list('id', flat=True)
|
|
|
|
eq_(sorted(addon_cats), [22, 24])
|
2010-12-10 06:51:46 +03:00
|
|
|
|
2010-12-18 07:00:32 +03:00
|
|
|
def test_edit_basic_categories_xss(self):
|
2011-01-06 23:36:36 +03:00
|
|
|
c = Category.objects.get(id=22)
|
|
|
|
c.name = '<script>alert("test");</script>'
|
|
|
|
c.save()
|
|
|
|
|
|
|
|
self.cat_initial['categories'] = [22, 24]
|
|
|
|
r = self.client.post(self.basic_url, formset(self.cat_initial,
|
|
|
|
initial_count=1))
|
2010-12-18 07:00:32 +03:00
|
|
|
|
|
|
|
assert '<script>alert' not in r.content
|
|
|
|
assert '<script>alert' in r.content
|
|
|
|
|
2010-12-10 06:51:46 +03:00
|
|
|
def test_edit_basic_categories_remove(self):
|
2011-01-06 23:36:36 +03:00
|
|
|
c = Category.objects.get(id=23)
|
|
|
|
AddonCategory(addon=self.addon, category=c).save()
|
|
|
|
eq_([c.id for c in self.get_addon().all_categories], [22, 23])
|
2010-12-10 06:51:46 +03:00
|
|
|
|
2011-01-06 23:36:36 +03:00
|
|
|
self.cat_initial['categories'] = [22]
|
2011-01-18 13:53:22 +03:00
|
|
|
self.client.post(self.basic_url, self.get_dict())
|
2010-12-10 06:51:46 +03:00
|
|
|
|
2011-01-13 01:27:31 +03:00
|
|
|
addon_cats = self.get_addon().categories.values_list('id', flat=True)
|
|
|
|
eq_(sorted(addon_cats), [22])
|
2010-12-10 06:51:46 +03:00
|
|
|
|
|
|
|
def test_edit_basic_categories_required(self):
|
2011-01-06 23:36:36 +03:00
|
|
|
del self.cat_initial['categories']
|
|
|
|
r = self.client.post(self.basic_url, formset(self.cat_initial,
|
|
|
|
initial_count=1))
|
|
|
|
eq_(r.context['cat_form'].errors[0]['categories'],
|
|
|
|
['This field is required.'])
|
2010-12-10 06:51:46 +03:00
|
|
|
|
|
|
|
def test_edit_basic_categories_max(self):
|
2011-01-06 23:36:36 +03:00
|
|
|
eq_(amo.MAX_CATEGORIES, 2)
|
|
|
|
self.cat_initial['categories'] = [22, 23, 24]
|
|
|
|
r = self.client.post(self.basic_url, formset(self.cat_initial,
|
|
|
|
initial_count=1))
|
|
|
|
eq_(r.context['cat_form'].errors[0]['categories'],
|
|
|
|
['You can have only 2 categories.'])
|
2010-12-10 06:51:46 +03:00
|
|
|
|
2010-12-15 22:41:41 +03:00
|
|
|
def test_edit_basic_categories_other_failure(self):
|
2011-01-06 23:36:36 +03:00
|
|
|
Category.objects.get(id=22).update(misc=True)
|
|
|
|
self.cat_initial['categories'] = [22, 23]
|
|
|
|
r = self.client.post(self.basic_url, formset(self.cat_initial,
|
|
|
|
initial_count=1))
|
|
|
|
eq_(r.context['cat_form'].errors[0]['categories'],
|
|
|
|
['The miscellaneous category cannot be combined with additional '
|
|
|
|
'categories.'])
|
2010-12-15 22:41:41 +03:00
|
|
|
|
2010-12-10 06:51:46 +03:00
|
|
|
def test_edit_basic_categories_nonexistent(self):
|
2011-01-06 23:36:36 +03:00
|
|
|
self.cat_initial['categories'] = [100]
|
|
|
|
r = self.client.post(self.basic_url, formset(self.cat_initial,
|
|
|
|
initial_count=1))
|
|
|
|
eq_(r.context['cat_form'].errors[0]['categories'],
|
|
|
|
['Select a valid choice. 100 is not one of the available '
|
|
|
|
'choices.'])
|
2010-12-10 06:51:46 +03:00
|
|
|
|
2010-11-11 22:33:39 +03:00
|
|
|
def test_edit_basic_name_not_empty(self):
|
2011-01-06 22:55:03 +03:00
|
|
|
data = self.get_dict(name='', slug=self.addon.slug,
|
|
|
|
summary=self.addon.summary)
|
2010-10-18 21:57:48 +04:00
|
|
|
r = self.client.post(self.get_url('basic', True), data)
|
2010-10-15 08:12:56 +04:00
|
|
|
self.assertFormError(r, 'form', 'name', 'This field is required.')
|
|
|
|
|
2010-11-09 07:11:07 +03:00
|
|
|
def test_edit_basic_name_max_length(self):
|
2011-01-06 22:55:03 +03:00
|
|
|
data = self.get_dict(name='xx' * 70, slug=self.addon.slug,
|
|
|
|
summary=self.addon.summary)
|
2010-11-09 07:11:07 +03:00
|
|
|
r = self.client.post(self.get_url('basic', True), data)
|
|
|
|
self.assertFormError(r, 'form', 'name',
|
2010-11-18 00:41:34 +03:00
|
|
|
'Ensure this value has at most 50 '
|
2010-11-09 07:11:07 +03:00
|
|
|
'characters (it has 140).')
|
|
|
|
|
|
|
|
def test_edit_basic_summary_max_length(self):
|
2011-01-06 22:55:03 +03:00
|
|
|
data = self.get_dict(name=self.addon.name, slug=self.addon.slug,
|
|
|
|
summary='x' * 251)
|
2010-11-09 07:11:07 +03:00
|
|
|
r = self.client.post(self.get_url('basic', True), data)
|
|
|
|
self.assertFormError(r, 'form', 'summary',
|
|
|
|
'Ensure this value has at most 250 '
|
|
|
|
'characters (it has 251).')
|
|
|
|
|
2010-10-15 08:12:56 +04:00
|
|
|
def test_edit_details(self):
|
|
|
|
data = dict(description='New description with <em>html</em>!',
|
2010-12-04 00:02:16 +03:00
|
|
|
default_locale='en-US',
|
2010-10-15 08:12:56 +04:00
|
|
|
homepage='http://twitter.com/fligtarsmom')
|
|
|
|
|
2010-10-18 21:57:48 +04:00
|
|
|
r = self.client.post(self.get_url('details', True), data)
|
2010-12-04 00:02:16 +03:00
|
|
|
eq_(r.context['form'].errors, {})
|
2010-10-15 08:12:56 +04:00
|
|
|
addon = self.get_addon()
|
|
|
|
|
|
|
|
for k in data:
|
|
|
|
eq_(unicode(getattr(addon, k)), data[k])
|
|
|
|
|
2011-01-07 01:43:47 +03:00
|
|
|
def test_edit_details_xss(self):
|
|
|
|
"""
|
|
|
|
Let's try to put xss in our description, and safe html, and verify
|
|
|
|
that we are playing safe.
|
|
|
|
"""
|
|
|
|
self.addon.description = ("This\n<b>IS</b>"
|
|
|
|
"<script>alert('awesome')</script>")
|
|
|
|
self.addon.save()
|
|
|
|
r = self.client.get(reverse('devhub.addons.edit',
|
|
|
|
args=[self.addon.slug]))
|
|
|
|
doc = pq(r.content)
|
|
|
|
eq_(doc('#edit-addon-details span[lang]').html(),
|
|
|
|
"This<br/><b>IS</b><script>alert('awesome')"
|
|
|
|
'</script>')
|
|
|
|
|
2010-11-22 23:11:51 +03:00
|
|
|
def test_edit_basic_homepage_optional(self):
|
|
|
|
data = dict(description='New description with <em>html</em>!',
|
2010-12-04 00:02:16 +03:00
|
|
|
default_locale='en-US', homepage='')
|
2010-11-22 23:11:51 +03:00
|
|
|
|
|
|
|
r = self.client.post(self.get_url('details', True), data)
|
2010-12-04 00:02:16 +03:00
|
|
|
eq_(r.context['form'].errors, {})
|
2010-11-22 23:11:51 +03:00
|
|
|
addon = self.get_addon()
|
|
|
|
|
|
|
|
for k in data:
|
|
|
|
eq_(unicode(getattr(addon, k)), data[k])
|
|
|
|
|
2010-12-04 00:02:16 +03:00
|
|
|
def test_edit_default_locale_required_trans(self):
|
|
|
|
# name, summary, and description are required in the new locale.
|
|
|
|
description, homepage = map(unicode, [self.addon.description,
|
|
|
|
self.addon.homepage])
|
|
|
|
# TODO: description should get fixed up with the form.
|
|
|
|
fields = ['description', 'name', 'summary']
|
2010-12-10 02:55:30 +03:00
|
|
|
error = ('Before changing your default locale you must have a name, '
|
2010-12-04 00:02:16 +03:00
|
|
|
'summary, and description in that locale. '
|
|
|
|
'You are missing %s.')
|
|
|
|
missing = lambda f: error % ', '.join(map(repr, f))
|
|
|
|
|
|
|
|
d = dict(description=description, homepage=homepage,
|
|
|
|
default_locale='fr')
|
|
|
|
r = self.client.post(self.get_url('details', True), d)
|
|
|
|
self.assertFormError(r, 'form', None, missing(fields))
|
|
|
|
|
|
|
|
# Now we have a name.
|
|
|
|
self.addon.name = {'fr': 'fr name'}
|
2010-12-27 19:20:55 +03:00
|
|
|
self.addon.save()
|
2010-12-04 00:02:16 +03:00
|
|
|
fields.remove('name')
|
|
|
|
r = self.client.post(self.get_url('details', True), d)
|
|
|
|
self.assertFormError(r, 'form', None, missing(fields))
|
|
|
|
|
|
|
|
# Now we have a summary.
|
|
|
|
self.addon.summary = {'fr': 'fr summary'}
|
2010-12-27 19:20:55 +03:00
|
|
|
self.addon.save()
|
2010-12-04 00:02:16 +03:00
|
|
|
fields.remove('summary')
|
|
|
|
r = self.client.post(self.get_url('details', True), d)
|
|
|
|
self.assertFormError(r, 'form', None, missing(fields))
|
|
|
|
|
|
|
|
# Now we're sending an fr description with the form.
|
|
|
|
d['description_fr'] = 'fr description'
|
|
|
|
r = self.client.post(self.get_url('details', True), d)
|
|
|
|
eq_(r.context['form'].errors, {})
|
|
|
|
|
2010-12-10 02:40:45 +03:00
|
|
|
def test_edit_default_locale_frontend_error(self):
|
|
|
|
d = dict(description='xx', homepage='yy', default_locale='fr')
|
|
|
|
r = self.client.post(self.get_url('details', True), d)
|
2010-12-10 02:55:30 +03:00
|
|
|
self.assertContains(r, 'Before changing your default locale you must')
|
2010-12-10 02:40:45 +03:00
|
|
|
|
2010-10-15 08:12:56 +04:00
|
|
|
def test_edit_details_locale(self):
|
|
|
|
addon = self.get_addon()
|
|
|
|
addon.update(default_locale='en-US')
|
|
|
|
|
2010-10-18 21:57:48 +04:00
|
|
|
r = self.client.get(self.get_url('details', False))
|
2010-10-15 08:12:56 +04:00
|
|
|
|
2010-12-04 00:02:16 +03:00
|
|
|
eq_(pq(r.content)('.addon_edit_locale').eq(0).text(), "English (US)")
|
2010-10-15 08:12:56 +04:00
|
|
|
|
2010-10-18 21:57:48 +04:00
|
|
|
def test_edit_support(self):
|
|
|
|
data = dict(support_email='sjobs@apple.com',
|
|
|
|
support_url='http://apple.com/')
|
|
|
|
|
|
|
|
r = self.client.post(self.get_url('support', True), data)
|
2010-12-04 00:02:16 +03:00
|
|
|
eq_(r.context['form'].errors, {})
|
2010-10-18 21:57:48 +04:00
|
|
|
addon = self.get_addon()
|
|
|
|
|
|
|
|
for k in data:
|
|
|
|
eq_(unicode(getattr(addon, k)), data[k])
|
|
|
|
|
|
|
|
def test_edit_support_getsatisfaction(self):
|
2010-12-03 02:43:38 +03:00
|
|
|
urls = [("http://getsatisfaction.com/abc/products/def", 'abcdef'),
|
|
|
|
("http://getsatisfaction.com/abc/", 'abc'), # No company
|
|
|
|
("http://google.com", None)] # Delete GS
|
2010-10-18 21:57:48 +04:00
|
|
|
|
|
|
|
for (url, val) in urls:
|
|
|
|
data = dict(support_email='abc@def.com',
|
|
|
|
support_url=url)
|
|
|
|
|
|
|
|
r = self.client.post(self.get_url('support', True), data)
|
2010-12-04 00:02:16 +03:00
|
|
|
eq_(r.context['form'].errors, {})
|
2010-10-18 21:57:48 +04:00
|
|
|
|
2010-12-04 00:02:16 +03:00
|
|
|
result = pq(r.content)('.addon_edit_gs').eq(0).text()
|
2010-12-03 02:43:38 +03:00
|
|
|
doc = pq(r.content)
|
|
|
|
result = doc('.addon_edit_gs').eq(0).text()
|
2010-10-18 21:57:48 +04:00
|
|
|
|
|
|
|
result = re.sub('\W', '', result) if result else None
|
|
|
|
|
|
|
|
eq_(result, val)
|
|
|
|
|
2010-11-22 23:11:51 +03:00
|
|
|
def test_edit_support_optional_url(self):
|
|
|
|
data = dict(support_email='sjobs@apple.com',
|
|
|
|
support_url='')
|
|
|
|
|
|
|
|
r = self.client.post(self.get_url('support', True), data)
|
2010-12-04 00:02:16 +03:00
|
|
|
eq_(r.context['form'].errors, {})
|
2010-11-22 23:11:51 +03:00
|
|
|
addon = self.get_addon()
|
|
|
|
|
|
|
|
for k in data:
|
|
|
|
eq_(unicode(getattr(addon, k)), data[k])
|
|
|
|
|
|
|
|
def test_edit_support_optional_email(self):
|
|
|
|
data = dict(support_email='',
|
|
|
|
support_url='http://apple.com/')
|
|
|
|
|
|
|
|
r = self.client.post(self.get_url('support', True), data)
|
2010-12-04 00:02:16 +03:00
|
|
|
eq_(r.context['form'].errors, {})
|
2010-11-22 23:11:51 +03:00
|
|
|
addon = self.get_addon()
|
|
|
|
|
|
|
|
for k in data:
|
|
|
|
eq_(unicode(getattr(addon, k)), data[k])
|
|
|
|
|
2010-12-10 03:36:00 +03:00
|
|
|
def test_edit_media_defaulticon(self):
|
|
|
|
data = dict(icon_type='')
|
2010-12-31 04:02:31 +03:00
|
|
|
data_formset = self.formset_media(**data)
|
2010-12-10 03:36:00 +03:00
|
|
|
|
2010-12-31 04:02:31 +03:00
|
|
|
r = self.client.post(self.get_url('media', True), data_formset)
|
2010-12-10 03:36:00 +03:00
|
|
|
eq_(r.context['form'].errors, {})
|
|
|
|
addon = self.get_addon()
|
|
|
|
|
2011-01-12 22:06:00 +03:00
|
|
|
assert addon.get_icon_url(64).endswith('icons/default-64.png')
|
2010-12-10 03:36:00 +03:00
|
|
|
|
|
|
|
for k in data:
|
|
|
|
eq_(unicode(getattr(addon, k)), data[k])
|
2011-01-12 22:06:00 +03:00
|
|
|
|
2010-12-10 03:36:00 +03:00
|
|
|
def test_edit_media_preuploadedicon(self):
|
|
|
|
data = dict(icon_type='icon/appearance')
|
2010-12-31 04:02:31 +03:00
|
|
|
data_formset = self.formset_media(**data)
|
2010-12-10 03:36:00 +03:00
|
|
|
|
2010-12-31 04:02:31 +03:00
|
|
|
r = self.client.post(self.get_url('media', True), data_formset)
|
2010-12-10 03:36:00 +03:00
|
|
|
eq_(r.context['form'].errors, {})
|
|
|
|
addon = self.get_addon()
|
|
|
|
|
|
|
|
assert addon.get_icon_url(64).endswith('icons/appearance-64.png')
|
|
|
|
|
|
|
|
for k in data:
|
|
|
|
eq_(unicode(getattr(addon, k)), data[k])
|
|
|
|
|
|
|
|
def test_edit_media_uploadedicon(self):
|
|
|
|
img = "%s/img/amo2009/tab-mozilla.png" % settings.MEDIA_ROOT
|
|
|
|
src_image = open(img, 'rb')
|
|
|
|
|
2011-01-12 02:53:58 +03:00
|
|
|
data = dict(upload_image=src_image)
|
|
|
|
|
|
|
|
response = self.client.post(self.icon_upload, data)
|
|
|
|
response_json = json.loads(response.content)
|
|
|
|
addon = self.get_addon()
|
|
|
|
|
|
|
|
# Now, save the form so it gets moved properly.
|
2010-12-10 03:36:00 +03:00
|
|
|
data = dict(icon_type='image/png',
|
2011-01-12 02:53:58 +03:00
|
|
|
icon_upload_hash=response_json['upload_hash'])
|
2010-12-31 04:02:31 +03:00
|
|
|
data_formset = self.formset_media(**data)
|
2010-12-10 03:36:00 +03:00
|
|
|
|
2010-12-31 04:02:31 +03:00
|
|
|
r = self.client.post(self.get_url('media', True), data_formset)
|
2010-12-10 03:36:00 +03:00
|
|
|
eq_(r.context['form'].errors, {})
|
|
|
|
addon = self.get_addon()
|
|
|
|
|
2011-01-12 02:53:58 +03:00
|
|
|
eq_('/'.join(addon.get_icon_url(64).split('/')[-3:-1]),
|
|
|
|
'addon_icon/%s' % addon.id)
|
2010-12-10 03:36:00 +03:00
|
|
|
|
|
|
|
eq_(data['icon_type'], 'image/png')
|
|
|
|
|
|
|
|
# Check that it was actually uploaded
|
2011-01-12 02:53:58 +03:00
|
|
|
dirname = os.path.join(settings.ADDON_ICONS_PATH,
|
|
|
|
'%s' % (addon.id / 1000))
|
2010-12-10 03:36:00 +03:00
|
|
|
dest = os.path.join(dirname, '%s-32.png' % addon.id)
|
|
|
|
|
|
|
|
assert os.path.exists(dest)
|
|
|
|
|
|
|
|
eq_(Image.open(dest).size, (32, 12))
|
|
|
|
|
2010-12-30 20:54:28 +03:00
|
|
|
def test_edit_media_icon_log(self):
|
|
|
|
self.test_edit_media_uploadedicon()
|
|
|
|
log = ActivityLog.objects.all()
|
|
|
|
eq_(log.count(), 1)
|
|
|
|
eq_(log[0].action, amo.LOG.CHANGE_ICON.id)
|
|
|
|
|
2010-12-10 03:36:00 +03:00
|
|
|
def test_edit_media_uploadedicon_noresize(self):
|
|
|
|
img = "%s/img/amo2009/notifications/error.png" % settings.MEDIA_ROOT
|
|
|
|
src_image = open(img, 'rb')
|
|
|
|
|
2011-01-12 02:53:58 +03:00
|
|
|
data = dict(upload_image=src_image)
|
|
|
|
|
|
|
|
response = self.client.post(self.icon_upload, data)
|
|
|
|
response_json = json.loads(response.content)
|
|
|
|
addon = self.get_addon()
|
|
|
|
|
|
|
|
# Now, save the form so it gets moved properly.
|
2010-12-10 03:36:00 +03:00
|
|
|
data = dict(icon_type='image/png',
|
2011-01-12 02:53:58 +03:00
|
|
|
icon_upload_hash=response_json['upload_hash'])
|
2010-12-31 04:02:31 +03:00
|
|
|
data_formset = self.formset_media(**data)
|
2010-12-10 03:36:00 +03:00
|
|
|
|
2010-12-31 04:02:31 +03:00
|
|
|
r = self.client.post(self.get_url('media', True), data_formset)
|
2010-12-10 03:36:00 +03:00
|
|
|
eq_(r.context['form'].errors, {})
|
|
|
|
addon = self.get_addon()
|
|
|
|
|
2011-01-12 02:53:58 +03:00
|
|
|
eq_('/'.join(addon.get_icon_url(64).split('/')[-3:-1]),
|
|
|
|
'addon_icon/%s' % addon.id)
|
2010-12-10 03:36:00 +03:00
|
|
|
|
|
|
|
eq_(data['icon_type'], 'image/png')
|
|
|
|
|
|
|
|
# Check that it was actually uploaded
|
|
|
|
dirname = os.path.join(settings.ADDON_ICONS_PATH,
|
|
|
|
'%s' % (addon.id / 1000))
|
|
|
|
dest = os.path.join(dirname, '%s-64.png' % addon.id)
|
2011-01-12 02:53:58 +03:00
|
|
|
|
2010-12-10 03:36:00 +03:00
|
|
|
assert os.path.exists(dest)
|
|
|
|
|
|
|
|
eq_(Image.open(dest).size, (48, 48))
|
|
|
|
|
|
|
|
def test_edit_media_uploadedicon_wrongtype(self):
|
2010-12-10 04:38:28 +03:00
|
|
|
img = "%s/js/zamboni/devhub.js" % settings.MEDIA_ROOT
|
2010-12-10 03:36:00 +03:00
|
|
|
src_image = open(img, 'rb')
|
|
|
|
|
2011-01-12 02:53:58 +03:00
|
|
|
data = {'upload_image': src_image}
|
2010-12-10 03:36:00 +03:00
|
|
|
|
2011-01-12 02:53:58 +03:00
|
|
|
res = self.client.post(self.preview_upload, data)
|
|
|
|
response_json = json.loads(res.content)
|
|
|
|
|
|
|
|
eq_(response_json['errors'][0], u'Icons must be either PNG or JPG.')
|
2010-12-10 03:36:00 +03:00
|
|
|
|
2011-01-05 01:26:30 +03:00
|
|
|
def setup_image_status(self):
|
2010-12-30 20:54:28 +03:00
|
|
|
addon = self.get_addon()
|
2011-01-05 01:26:30 +03:00
|
|
|
self.icon_dest = os.path.join(addon.get_icon_dir(),
|
|
|
|
'%s-32.png' % addon.id)
|
|
|
|
os.makedirs(os.path.dirname(self.icon_dest))
|
|
|
|
open(self.icon_dest, 'w')
|
|
|
|
|
|
|
|
self.preview = addon.previews.create()
|
|
|
|
self.preview.save()
|
|
|
|
os.makedirs(os.path.dirname(self.preview.thumbnail_path))
|
|
|
|
open(self.preview.thumbnail_path, 'w')
|
|
|
|
|
|
|
|
self.url = reverse('devhub.ajax.image.status', args=[addon.slug])
|
|
|
|
|
2011-02-01 19:31:17 +03:00
|
|
|
def test_image_status_no_choice(self):
|
|
|
|
addon = self.get_addon()
|
|
|
|
addon.update(icon_type='')
|
|
|
|
url = reverse('devhub.ajax.image.status', args=[addon.slug])
|
|
|
|
result = json.loads(self.client.get(url).content)
|
|
|
|
assert result['icons']
|
|
|
|
|
2011-01-05 01:26:30 +03:00
|
|
|
def test_image_status_works(self):
|
|
|
|
self.setup_image_status()
|
|
|
|
result = json.loads(self.client.get(self.url).content)
|
|
|
|
assert result['icons']
|
|
|
|
|
|
|
|
def test_image_status_fails(self):
|
|
|
|
self.setup_image_status()
|
2010-12-30 20:54:28 +03:00
|
|
|
os.remove(self.icon_dest)
|
2011-01-05 01:26:30 +03:00
|
|
|
result = json.loads(self.client.get(self.url).content)
|
|
|
|
assert not result['icons']
|
|
|
|
|
|
|
|
def test_preview_status_works(self):
|
|
|
|
self.setup_image_status()
|
|
|
|
result = json.loads(self.client.get(self.url).content)
|
|
|
|
assert result['previews']
|
|
|
|
|
|
|
|
# No previews means that all the images are done.
|
|
|
|
self.addon.previews.all().delete()
|
|
|
|
result = json.loads(self.client.get(self.url).content)
|
|
|
|
assert result['previews']
|
|
|
|
|
|
|
|
def test_preview_status_fails(self):
|
|
|
|
self.setup_image_status()
|
|
|
|
os.remove(self.preview.thumbnail_path)
|
|
|
|
result = json.loads(self.client.get(self.url).content)
|
|
|
|
assert not result['previews']
|
2010-12-30 20:54:28 +03:00
|
|
|
|
2011-01-13 21:41:22 +03:00
|
|
|
def test_image_status_persona(self):
|
|
|
|
self.setup_image_status()
|
|
|
|
os.remove(self.icon_dest)
|
|
|
|
self.get_addon().update(type=amo.ADDON_PERSONA)
|
|
|
|
result = json.loads(self.client.get(self.url).content)
|
|
|
|
assert result['icons']
|
|
|
|
|
|
|
|
def test_image_status_default(self):
|
|
|
|
self.setup_image_status()
|
|
|
|
os.remove(self.icon_dest)
|
|
|
|
self.get_addon().update(icon_type='icon/photos')
|
|
|
|
result = json.loads(self.client.get(self.url).content)
|
|
|
|
assert result['icons']
|
|
|
|
|
2010-12-10 22:52:26 +03:00
|
|
|
def test_icon_animated(self):
|
|
|
|
filehandle = open(get_image_path('animated.png'), 'rb')
|
2011-01-12 02:53:58 +03:00
|
|
|
data = {'upload_image': filehandle}
|
|
|
|
|
|
|
|
res = self.client.post(self.preview_upload, data)
|
|
|
|
response_json = json.loads(res.content)
|
|
|
|
|
|
|
|
eq_(response_json['errors'][0], u'Icons cannot be animated.')
|
2010-12-10 22:52:26 +03:00
|
|
|
|
2010-12-31 04:02:31 +03:00
|
|
|
def preview_add(self, amount=1):
|
|
|
|
img = "%s/img/amo2009/tab-mozilla.png" % settings.MEDIA_ROOT
|
|
|
|
src_image = open(img, 'rb')
|
|
|
|
|
2011-01-12 02:53:58 +03:00
|
|
|
data = dict(upload_image=src_image)
|
2010-12-31 04:02:31 +03:00
|
|
|
data_formset = self.formset_media(**data)
|
2011-01-12 02:53:58 +03:00
|
|
|
url = self.preview_upload
|
|
|
|
|
2010-12-31 04:02:31 +03:00
|
|
|
r = self.client.post(url, data_formset)
|
|
|
|
|
|
|
|
details = json.loads(r.content)
|
|
|
|
upload_hash = details['upload_hash']
|
|
|
|
|
|
|
|
# Create and post with the formset.
|
|
|
|
fields = []
|
|
|
|
for i in range(amount):
|
|
|
|
fields.append(self.formset_new_form(caption='hi',
|
2011-01-11 22:53:03 +03:00
|
|
|
upload_hash=upload_hash,
|
|
|
|
position=i))
|
2010-12-31 04:02:31 +03:00
|
|
|
data_formset = self.formset_media(*fields)
|
|
|
|
|
|
|
|
self.get_url('media', True)
|
|
|
|
|
|
|
|
r = self.client.post(self.get_url('media', True), data_formset)
|
|
|
|
|
|
|
|
def test_edit_media_preview_add(self):
|
|
|
|
self.preview_add()
|
|
|
|
|
|
|
|
eq_(str(self.get_addon().previews.all()[0].caption), 'hi')
|
|
|
|
|
|
|
|
def test_edit_media_preview_edit(self):
|
|
|
|
self.preview_add()
|
|
|
|
preview = self.get_addon().previews.all()[0]
|
|
|
|
edited = {'caption': 'bye',
|
|
|
|
'upload_hash': '',
|
|
|
|
'id': preview.id,
|
2011-01-11 22:53:03 +03:00
|
|
|
'position': preview.position,
|
2010-12-31 04:02:31 +03:00
|
|
|
'file_upload': None}
|
|
|
|
|
|
|
|
data_formset = self.formset_media(edited, initial_count=1)
|
|
|
|
|
|
|
|
self.client.post(self.get_url('media', True), data_formset)
|
|
|
|
|
|
|
|
eq_(str(self.get_addon().previews.all()[0].caption), 'bye')
|
|
|
|
eq_(len(self.get_addon().previews.all()), 1)
|
|
|
|
|
2011-01-11 22:53:03 +03:00
|
|
|
def test_edit_media_preview_reorder(self):
|
|
|
|
self.preview_add(3)
|
|
|
|
|
|
|
|
previews = self.get_addon().previews.all()
|
|
|
|
|
|
|
|
base = dict(upload_hash='', file_upload=None)
|
|
|
|
|
|
|
|
# Three preview forms were generated; mix them up here.
|
|
|
|
a = dict(caption="first", position=1, id=previews[2].id)
|
|
|
|
b = dict(caption="second", position=2, id=previews[0].id)
|
|
|
|
c = dict(caption="third", position=3, id=previews[1].id)
|
|
|
|
a.update(base)
|
|
|
|
b.update(base)
|
|
|
|
c.update(base)
|
|
|
|
|
|
|
|
# Add them in backwards ("third", "second", "first")
|
|
|
|
data_formset = self.formset_media(c, b, a, initial_count=3)
|
|
|
|
eq_(data_formset['files-0-caption'], 'third')
|
|
|
|
eq_(data_formset['files-1-caption'], 'second')
|
|
|
|
eq_(data_formset['files-2-caption'], 'first')
|
|
|
|
|
|
|
|
self.client.post(self.get_url('media', True), data_formset)
|
|
|
|
|
|
|
|
# They should come out "first", "second", "third"
|
|
|
|
eq_(self.get_addon().previews.all()[0].caption, 'first')
|
|
|
|
eq_(self.get_addon().previews.all()[1].caption, 'second')
|
|
|
|
eq_(self.get_addon().previews.all()[2].caption, 'third')
|
|
|
|
|
2011-01-06 02:29:35 +03:00
|
|
|
def test_edit_media_preview_delete(self):
|
|
|
|
self.preview_add()
|
|
|
|
preview = self.get_addon().previews.get()
|
|
|
|
edited = {'DELETE': 'checked',
|
|
|
|
'upload_hash': '',
|
|
|
|
'id': preview.id,
|
2011-01-11 22:53:03 +03:00
|
|
|
'position': 0,
|
2011-01-06 02:29:35 +03:00
|
|
|
'file_upload': None}
|
|
|
|
|
|
|
|
data_formset = self.formset_media(edited, initial_count=1)
|
|
|
|
|
|
|
|
self.client.post(self.get_url('media', True), data_formset)
|
|
|
|
|
|
|
|
eq_(len(self.get_addon().previews.all()), 0)
|
|
|
|
|
2010-12-31 04:02:31 +03:00
|
|
|
def test_edit_media_preview_add_another(self):
|
|
|
|
self.preview_add()
|
|
|
|
self.preview_add()
|
|
|
|
|
|
|
|
eq_(len(self.get_addon().previews.all()), 2)
|
|
|
|
|
|
|
|
def test_edit_media_preview_add_two(self):
|
|
|
|
self.preview_add(2)
|
|
|
|
|
|
|
|
eq_(len(self.get_addon().previews.all()), 2)
|
|
|
|
|
2010-11-02 20:45:45 +03:00
|
|
|
def test_log(self):
|
|
|
|
data = {'developer_comments': 'This is a test'}
|
|
|
|
o = ActivityLog.objects
|
|
|
|
eq_(o.count(), 0)
|
|
|
|
r = self.client.post(self.get_url('technical', True), data)
|
2010-12-04 00:02:16 +03:00
|
|
|
eq_(r.context['form'].errors, {})
|
2010-11-02 20:45:45 +03:00
|
|
|
eq_(o.filter(action=amo.LOG.EDIT_PROPERTIES.id).count(), 1)
|
|
|
|
|
2010-10-18 21:57:48 +04:00
|
|
|
def test_technical_on(self):
|
|
|
|
# Turn everything on
|
|
|
|
data = dict(developer_comments='Test comment!',
|
|
|
|
binary='on',
|
|
|
|
external_software='on',
|
|
|
|
site_specific='on',
|
|
|
|
view_source='on')
|
|
|
|
|
|
|
|
r = self.client.post(self.get_url('technical', True), data)
|
2010-12-04 00:02:16 +03:00
|
|
|
eq_(r.context['form'].errors, {})
|
2010-10-18 21:57:48 +04:00
|
|
|
|
|
|
|
addon = self.get_addon()
|
|
|
|
for k in data:
|
|
|
|
if k == 'developer_comments':
|
|
|
|
eq_(unicode(getattr(addon, k)), unicode(data[k]))
|
|
|
|
else:
|
|
|
|
eq_(getattr(addon, k), True if data[k] == 'on' else False)
|
|
|
|
|
|
|
|
# Andddd offf
|
|
|
|
data = dict(developer_comments='Test comment!')
|
|
|
|
r = self.client.post(self.get_url('technical', True), data)
|
|
|
|
addon = self.get_addon()
|
|
|
|
|
|
|
|
eq_(addon.binary, False)
|
|
|
|
eq_(addon.external_software, False)
|
|
|
|
eq_(addon.site_specific, False)
|
|
|
|
eq_(addon.view_source, False)
|
|
|
|
|
2010-12-31 09:13:24 +03:00
|
|
|
def test_technical_devcomment_notrequired(self):
|
|
|
|
data = dict(developer_comments='',
|
|
|
|
binary='on',
|
|
|
|
external_software='on',
|
|
|
|
site_specific='on',
|
|
|
|
view_source='on')
|
|
|
|
|
|
|
|
r = self.client.post(self.get_url('technical', True), data)
|
|
|
|
eq_(r.context['form'].errors, {})
|
|
|
|
|
|
|
|
addon = self.get_addon()
|
|
|
|
for k in data:
|
|
|
|
if k == 'developer_comments':
|
|
|
|
eq_(unicode(getattr(addon, k)), unicode(data[k]))
|
|
|
|
else:
|
|
|
|
eq_(getattr(addon, k), True if data[k] == 'on' else False)
|
|
|
|
|
2010-11-30 02:36:13 +03:00
|
|
|
def test_nav_links(self):
|
2010-12-20 23:47:01 +03:00
|
|
|
url = reverse('devhub.addons.edit', args=['a3615'])
|
|
|
|
activity_url = reverse('devhub.feed', args=['a3615'])
|
2010-11-30 02:36:13 +03:00
|
|
|
r = self.client.get(url)
|
|
|
|
doc = pq(r.content)
|
2010-11-30 01:18:05 +03:00
|
|
|
eq_(doc('#edit-addon-nav ul:last').find('li a').eq(1).attr('href'),
|
|
|
|
activity_url)
|
2010-11-30 02:36:13 +03:00
|
|
|
|
2010-12-02 01:18:33 +03:00
|
|
|
def get_l10n_urls(self):
|
|
|
|
paths = ('devhub.addons.edit', 'devhub.addons.profile',
|
|
|
|
'devhub.addons.payments', 'devhub.addons.owner')
|
2010-12-20 23:47:01 +03:00
|
|
|
return [reverse(p, args=['a3615']) for p in paths]
|
2010-12-02 01:18:33 +03:00
|
|
|
|
|
|
|
def test_l10n(self):
|
2010-12-02 20:23:37 +03:00
|
|
|
Addon.objects.get(id=3615).update(default_locale='en-US')
|
2010-12-02 01:18:33 +03:00
|
|
|
for url in self.get_l10n_urls():
|
|
|
|
r = self.client.get(url)
|
2010-12-04 00:02:16 +03:00
|
|
|
eq_(pq(r.content)('#l10n-menu').attr('data-default'), 'en-us')
|
2010-12-02 01:18:33 +03:00
|
|
|
|
|
|
|
def test_l10n_not_us(self):
|
2010-12-02 20:23:37 +03:00
|
|
|
Addon.objects.get(id=3615).update(default_locale='fr')
|
2010-12-02 01:18:33 +03:00
|
|
|
for url in self.get_l10n_urls():
|
|
|
|
r = self.client.get(url)
|
2010-12-04 00:02:16 +03:00
|
|
|
eq_(pq(r.content)('#l10n-menu').attr('data-default'), 'fr')
|
2010-12-02 01:18:33 +03:00
|
|
|
|
|
|
|
def test_l10n_not_us_id_url(self):
|
2010-12-02 20:23:37 +03:00
|
|
|
Addon.objects.get(id=3615).update(default_locale='fr')
|
2010-12-02 01:18:33 +03:00
|
|
|
for url in self.get_l10n_urls():
|
|
|
|
url = '/id' + url[6:]
|
|
|
|
r = self.client.get(url)
|
2010-12-04 00:02:16 +03:00
|
|
|
eq_(pq(r.content)('#l10n-menu').attr('data-default'), 'fr')
|
2010-12-02 01:18:33 +03:00
|
|
|
|
2010-10-11 02:51:45 +04:00
|
|
|
|
2010-12-27 21:01:51 +03:00
|
|
|
class TestActivityFeed(test_utils.TestCase):
|
|
|
|
fixtures = ('base/apps', 'base/users', 'base/addon_3615')
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
super(TestActivityFeed, self).setUp()
|
|
|
|
assert self.client.login(username='del@icio.us', password='password')
|
|
|
|
|
|
|
|
def test_feed_for_all(self):
|
|
|
|
r = self.client.get(reverse('devhub.feed_all'))
|
|
|
|
eq_(r.status_code, 200)
|
|
|
|
doc = pq(r.content)
|
|
|
|
eq_(doc('header h2').text(),
|
|
|
|
'Recent Activity for My Add-ons')
|
|
|
|
eq_(doc('.breadcrumbs li:eq(2)').text(),
|
|
|
|
'Recent Activity')
|
|
|
|
|
|
|
|
def test_feed_for_addon(self):
|
|
|
|
addon = Addon.objects.no_cache().get(id=3615)
|
|
|
|
r = self.client.get(reverse('devhub.feed', args=[addon.slug]))
|
|
|
|
eq_(r.status_code, 200)
|
|
|
|
doc = pq(r.content)
|
|
|
|
eq_(doc('header h2').text(),
|
|
|
|
'Recent Activity for %s' % addon.name)
|
|
|
|
eq_(doc('.breadcrumbs li:eq(3)').text(),
|
|
|
|
addon.slug)
|
|
|
|
|
|
|
|
|
2010-11-11 03:19:37 +03:00
|
|
|
class TestProfileBase(test_utils.TestCase):
|
2010-10-11 02:51:45 +04:00
|
|
|
fixtures = ['base/apps', 'base/users', 'base/addon_3615']
|
|
|
|
|
|
|
|
def setUp(self):
|
2010-12-20 23:47:01 +03:00
|
|
|
self.url = reverse('devhub.addons.profile', args=['a3615'])
|
2010-10-11 02:51:45 +04:00
|
|
|
assert self.client.login(username='del@icio.us', password='password')
|
|
|
|
self.addon = Addon.objects.get(id=3615)
|
|
|
|
self.version = self.addon.current_version
|
|
|
|
|
|
|
|
def get_addon(self):
|
|
|
|
return Addon.objects.no_cache().get(id=self.addon.id)
|
|
|
|
|
|
|
|
def enable_addon_contributions(self):
|
|
|
|
self.addon.wants_contributions = True
|
|
|
|
self.addon.paypal_id = 'somebody'
|
|
|
|
self.addon.save()
|
|
|
|
|
|
|
|
def post(self, *args, **kw):
|
|
|
|
d = dict(*args, **kw)
|
|
|
|
eq_(self.client.post(self.url, d).status_code, 302)
|
|
|
|
|
|
|
|
def check(self, **kw):
|
|
|
|
addon = self.get_addon()
|
|
|
|
for k, v in kw.items():
|
|
|
|
if k in ('the_reason', 'the_future'):
|
|
|
|
eq_(getattr(getattr(addon, k), 'localized_string'), unicode(v))
|
|
|
|
else:
|
|
|
|
eq_(getattr(addon, k), v)
|
2010-11-11 03:19:37 +03:00
|
|
|
|
|
|
|
|
|
|
|
class TestProfileStatusBar(TestProfileBase):
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
super(TestProfileStatusBar, self).setUp()
|
|
|
|
self.remove_url = reverse('devhub.addons.profile.remove',
|
2010-12-20 23:47:01 +03:00
|
|
|
args=[self.addon.slug])
|
2010-11-11 03:19:37 +03:00
|
|
|
|
|
|
|
def test_no_status_bar(self):
|
|
|
|
self.addon.the_reason = self.addon.the_future = None
|
|
|
|
self.addon.save()
|
|
|
|
assert not pq(self.client.get(self.url).content)('#status-bar')
|
|
|
|
|
|
|
|
def test_status_bar_no_contrib(self):
|
|
|
|
self.addon.the_reason = self.addon.the_future = '...'
|
|
|
|
self.addon.wants_contributions = False
|
|
|
|
self.addon.save()
|
|
|
|
doc = pq(self.client.get(self.url).content)
|
|
|
|
assert doc('#status-bar')
|
|
|
|
eq_(doc('#status-bar button').text(), 'Remove Profile')
|
|
|
|
|
|
|
|
def test_status_bar_with_contrib(self):
|
|
|
|
self.addon.the_reason = self.addon.the_future = '...'
|
|
|
|
self.addon.wants_contributions = True
|
|
|
|
self.addon.paypal_id = 'xxx'
|
|
|
|
self.addon.save()
|
|
|
|
doc = pq(self.client.get(self.url).content)
|
|
|
|
assert doc('#status-bar')
|
|
|
|
eq_(doc('#status-bar button').text(), 'Remove Both')
|
|
|
|
|
|
|
|
def test_remove_profile(self):
|
|
|
|
self.addon.the_reason = self.addon.the_future = '...'
|
|
|
|
self.addon.save()
|
|
|
|
self.client.post(self.remove_url)
|
|
|
|
addon = self.get_addon()
|
|
|
|
eq_(addon.the_reason, None)
|
|
|
|
eq_(addon.the_future, None)
|
|
|
|
eq_(addon.takes_contributions, False)
|
|
|
|
eq_(addon.wants_contributions, False)
|
|
|
|
|
2011-01-12 02:24:30 +03:00
|
|
|
def test_remove_profile_without_content(self):
|
|
|
|
# See bug 624852
|
|
|
|
self.addon.the_reason = self.addon.the_future = None
|
|
|
|
self.addon.save()
|
|
|
|
self.client.post(self.remove_url)
|
|
|
|
addon = self.get_addon()
|
|
|
|
eq_(addon.the_reason, None)
|
|
|
|
eq_(addon.the_future, None)
|
|
|
|
|
2010-11-11 03:19:37 +03:00
|
|
|
def test_remove_both(self):
|
|
|
|
self.addon.the_reason = self.addon.the_future = '...'
|
|
|
|
self.addon.wants_contributions = True
|
|
|
|
self.addon.paypal_id = 'xxx'
|
|
|
|
self.addon.save()
|
|
|
|
self.client.post(self.remove_url)
|
|
|
|
addon = self.get_addon()
|
|
|
|
eq_(addon.the_reason, None)
|
|
|
|
eq_(addon.the_future, None)
|
|
|
|
eq_(addon.takes_contributions, False)
|
|
|
|
eq_(addon.wants_contributions, False)
|
|
|
|
|
|
|
|
|
|
|
|
class TestProfile(TestProfileBase):
|
2010-10-11 02:51:45 +04:00
|
|
|
|
|
|
|
def test_without_contributions_labels(self):
|
|
|
|
r = self.client.get(self.url)
|
|
|
|
doc = pq(r.content)
|
2010-11-30 02:31:53 +03:00
|
|
|
eq_(doc('label[for=the_reason] .optional').length, 1)
|
|
|
|
eq_(doc('label[for=the_future] .optional').length, 1)
|
2010-10-11 02:51:45 +04:00
|
|
|
|
|
|
|
def test_without_contributions_fields_optional(self):
|
|
|
|
self.post(the_reason='', the_future='')
|
|
|
|
self.check(the_reason='', the_future='')
|
|
|
|
|
|
|
|
self.post(the_reason='to be cool', the_future='')
|
|
|
|
self.check(the_reason='to be cool', the_future='')
|
|
|
|
|
|
|
|
self.post(the_reason='', the_future='hot stuff')
|
|
|
|
self.check(the_reason='', the_future='hot stuff')
|
|
|
|
|
|
|
|
self.post(the_reason='to be hot', the_future='cold stuff')
|
|
|
|
self.check(the_reason='to be hot', the_future='cold stuff')
|
|
|
|
|
|
|
|
def test_with_contributions_labels(self):
|
|
|
|
self.enable_addon_contributions()
|
|
|
|
r = self.client.get(self.url)
|
|
|
|
doc = pq(r.content)
|
2010-11-30 02:31:53 +03:00
|
|
|
assert doc('label[for=the_reason] .req').length, \
|
2010-10-11 02:51:45 +04:00
|
|
|
'the_reason field should be required.'
|
2010-11-30 02:31:53 +03:00
|
|
|
assert doc('label[for=the_future] .req').length, \
|
2010-10-11 02:51:45 +04:00
|
|
|
'the_future field should be required.'
|
|
|
|
|
2010-11-02 20:45:45 +03:00
|
|
|
def test_log(self):
|
|
|
|
self.enable_addon_contributions()
|
|
|
|
d = dict(the_reason='because', the_future='i can')
|
|
|
|
o = ActivityLog.objects
|
|
|
|
eq_(o.count(), 0)
|
2010-11-06 00:51:28 +03:00
|
|
|
self.client.post(self.url, d)
|
2010-11-02 20:45:45 +03:00
|
|
|
eq_(o.filter(action=amo.LOG.EDIT_PROPERTIES.id).count(), 1)
|
|
|
|
|
2010-10-11 02:51:45 +04:00
|
|
|
def test_with_contributions_fields_required(self):
|
|
|
|
self.enable_addon_contributions()
|
|
|
|
|
|
|
|
d = dict(the_reason='', the_future='')
|
|
|
|
r = self.client.post(self.url, d)
|
|
|
|
eq_(r.status_code, 200)
|
|
|
|
self.assertFormError(r, 'profile_form', 'the_reason',
|
|
|
|
'This field is required.')
|
|
|
|
self.assertFormError(r, 'profile_form', 'the_future',
|
|
|
|
'This field is required.')
|
|
|
|
|
|
|
|
d = dict(the_reason='to be cool', the_future='')
|
|
|
|
r = self.client.post(self.url, d)
|
|
|
|
eq_(r.status_code, 200)
|
|
|
|
self.assertFormError(r, 'profile_form', 'the_future',
|
|
|
|
'This field is required.')
|
|
|
|
|
|
|
|
d = dict(the_reason='', the_future='hot stuff')
|
|
|
|
r = self.client.post(self.url, d)
|
|
|
|
eq_(r.status_code, 200)
|
|
|
|
self.assertFormError(r, 'profile_form', 'the_reason',
|
|
|
|
'This field is required.')
|
|
|
|
|
|
|
|
self.post(the_reason='to be hot', the_future='cold stuff')
|
|
|
|
self.check(the_reason='to be hot', the_future='cold stuff')
|
2010-10-15 05:22:44 +04:00
|
|
|
|
|
|
|
|
2010-10-20 21:40:20 +04:00
|
|
|
def initial(form):
|
|
|
|
"""Gather initial data from the form into a dict."""
|
|
|
|
data = {}
|
|
|
|
for name, field in form.fields.items():
|
|
|
|
if form.is_bound:
|
|
|
|
data[name] = form[name].data
|
|
|
|
else:
|
|
|
|
data[name] = form.initial.get(name, field.initial)
|
|
|
|
# The browser sends nothing for an unchecked checkbox.
|
|
|
|
if isinstance(field, forms.BooleanField):
|
|
|
|
val = field.to_python(data[name])
|
|
|
|
if not val:
|
|
|
|
del data[name]
|
|
|
|
return data
|
|
|
|
|
|
|
|
|
2010-11-19 22:32:13 +03:00
|
|
|
class TestVersion(test_utils.TestCase):
|
|
|
|
fixtures = ['base/users',
|
|
|
|
'base/addon_3615']
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
assert self.client.login(username='del@icio.us', password='password')
|
2010-12-04 00:49:55 +03:00
|
|
|
self.user = UserProfile.objects.get(email='del@icio.us')
|
2010-11-19 22:32:13 +03:00
|
|
|
self.addon = Addon.objects.get(id=3615)
|
2010-11-20 00:51:36 +03:00
|
|
|
self.version = Version.objects.get(id=81551)
|
2010-12-20 23:47:01 +03:00
|
|
|
self.url = reverse('devhub.versions', args=['a3615'])
|
2010-11-19 22:32:13 +03:00
|
|
|
|
2010-12-20 23:47:01 +03:00
|
|
|
self.disable_url = reverse('devhub.addons.disable', args=['a3615'])
|
|
|
|
self.enable_url = reverse('devhub.addons.enable', args=['a3615'])
|
|
|
|
self.delete_url = reverse('devhub.versions.delete', args=['a3615'])
|
2010-11-20 06:18:56 +03:00
|
|
|
self.delete_data = {'addon_id': self.addon.pk,
|
|
|
|
'version_id': self.version.pk}
|
2010-11-20 00:51:36 +03:00
|
|
|
|
2010-12-30 00:13:43 +03:00
|
|
|
def get_doc(self):
|
|
|
|
res = self.client.get(self.url)
|
|
|
|
eq_(res.status_code, 200)
|
|
|
|
return pq(res.content)
|
2010-11-30 01:58:10 +03:00
|
|
|
|
2010-12-30 00:13:43 +03:00
|
|
|
def test_version_status_public(self):
|
|
|
|
doc = self.get_doc()
|
2010-12-07 20:47:48 +03:00
|
|
|
assert doc('#version-status')
|
2010-11-19 22:32:13 +03:00
|
|
|
|
|
|
|
self.addon.status = amo.STATUS_DISABLED
|
|
|
|
self.addon.save()
|
2010-12-30 00:13:43 +03:00
|
|
|
doc = self.get_doc()
|
2010-12-07 20:47:48 +03:00
|
|
|
assert doc('#version-status .status-admin-disabled')
|
|
|
|
eq_(doc('#version-status strong').text(),
|
2010-12-28 18:52:11 +03:00
|
|
|
'This add-on has been disabled by Mozilla .')
|
2010-11-30 01:58:10 +03:00
|
|
|
|
2010-12-07 20:47:48 +03:00
|
|
|
self.addon.update(disabled_by_user=True)
|
2010-12-30 00:13:43 +03:00
|
|
|
doc = self.get_doc()
|
2010-12-07 20:47:48 +03:00
|
|
|
eq_(doc('#version-status strong').text(),
|
2010-12-28 18:52:11 +03:00
|
|
|
'You have disabled this add-on.')
|
2010-11-19 22:32:13 +03:00
|
|
|
|
2010-12-30 00:13:43 +03:00
|
|
|
def test_no_validation_results(self):
|
|
|
|
doc = self.get_doc()
|
|
|
|
v = doc('td.file-validation').text()
|
2010-12-30 01:30:08 +03:00
|
|
|
eq_(re.sub(r'\s+', ' ', v),
|
2011-01-17 14:44:01 +03:00
|
|
|
'All Platforms Not validated. Validate now.')
|
2010-12-30 01:30:08 +03:00
|
|
|
eq_(doc('td.file-validation a').attr('href'),
|
|
|
|
reverse('devhub.file_validation',
|
|
|
|
args=[self.addon.slug, self.version.all_files[0].id]))
|
2010-12-30 00:13:43 +03:00
|
|
|
|
2011-01-12 02:16:26 +03:00
|
|
|
def test_delete_message(self):
|
|
|
|
"""Make sure we warn our users of the pain they will feel."""
|
|
|
|
r = self.client.get(self.url)
|
|
|
|
doc = pq(r.content)
|
|
|
|
eq_(doc('#modal-delete p').eq(0).text(),
|
|
|
|
'Deleting your add-on will permanently remove it from the site '
|
|
|
|
'and prevent its GUID from being submitted ever again, even by '
|
|
|
|
'you. The existing users of your add-on will remain on this '
|
|
|
|
'update channel and never receive updates again.')
|
|
|
|
|
2011-01-28 03:26:04 +03:00
|
|
|
def test_delete_message_if_bits_are_messy(self):
|
|
|
|
"""Make sure we warn krupas of the pain they will feel."""
|
|
|
|
self.addon.highest_status = amo.STATUS_NULL
|
|
|
|
self.addon.status = amo.STATUS_UNREVIEWED
|
|
|
|
self.addon.save()
|
|
|
|
|
|
|
|
r = self.client.get(self.url)
|
|
|
|
doc = pq(r.content)
|
|
|
|
eq_(doc('#modal-delete p').eq(0).text(),
|
|
|
|
'Deleting your add-on will permanently remove it from the site '
|
|
|
|
'and prevent its GUID from being submitted ever again, even by '
|
|
|
|
'you. The existing users of your add-on will remain on this '
|
|
|
|
'update channel and never receive updates again.')
|
|
|
|
|
2011-01-12 02:16:26 +03:00
|
|
|
def test_delete_message_incomplete(self):
|
|
|
|
"""
|
|
|
|
If an addon has highest_status = 0, they shouldn't be bothered with a
|
|
|
|
blacklisting threat if they hit delete.
|
|
|
|
"""
|
|
|
|
self.addon.highest_status = amo.STATUS_NULL
|
2011-01-28 03:26:04 +03:00
|
|
|
self.addon.status = amo.STATUS_NULL
|
2011-01-12 02:16:26 +03:00
|
|
|
self.addon.save()
|
|
|
|
r = self.client.get(self.url)
|
|
|
|
doc = pq(r.content)
|
|
|
|
# Normally 2 paragraphs, one is the warning which we should take out.
|
|
|
|
eq_(len(doc('#modal-delete p')), 1, 'We might be lying to our users.')
|
|
|
|
|
2010-11-20 00:51:36 +03:00
|
|
|
def test_delete_version(self):
|
2010-11-20 06:18:56 +03:00
|
|
|
self.client.post(self.delete_url, self.delete_data)
|
2010-11-20 00:51:36 +03:00
|
|
|
assert not Version.objects.filter(pk=81551).exists()
|
|
|
|
|
2011-01-17 18:32:06 +03:00
|
|
|
def test_delete_version_then_detail(self):
|
|
|
|
version, file = self._extra_version_and_file(amo.STATUS_LITE)
|
|
|
|
self.client.post(self.delete_url, self.delete_data)
|
|
|
|
res = self.client.get(reverse('addons.detail', args=[self.addon.slug]))
|
|
|
|
eq_(res.status_code, 200)
|
|
|
|
|
2010-11-20 00:51:36 +03:00
|
|
|
def test_cant_delete_version(self):
|
|
|
|
self.client.logout()
|
|
|
|
res = self.client.post(self.delete_url, self.delete_data)
|
|
|
|
eq_(res.status_code, 302)
|
|
|
|
assert Version.objects.filter(pk=81551).exists()
|
2010-11-19 22:32:13 +03:00
|
|
|
|
2010-12-04 00:49:55 +03:00
|
|
|
def test_version_delete_status_null(self):
|
|
|
|
res = self.client.post(self.delete_url, self.delete_data)
|
|
|
|
eq_(res.status_code, 302)
|
|
|
|
eq_(self.addon.versions.count(), 0)
|
|
|
|
eq_(Addon.objects.get(id=3615).status, amo.STATUS_NULL)
|
|
|
|
|
|
|
|
def _extra_version_and_file(self, status):
|
|
|
|
version = Version.objects.get(id=81551)
|
|
|
|
|
|
|
|
version_two = Version(addon=self.addon,
|
|
|
|
license=version.license,
|
|
|
|
version='1.2.3')
|
|
|
|
version_two.save()
|
|
|
|
|
|
|
|
file_two = File(status=status, version=version_two)
|
|
|
|
file_two.save()
|
|
|
|
return version_two, file_two
|
|
|
|
|
|
|
|
def test_version_delete_status(self):
|
|
|
|
self._extra_version_and_file(amo.STATUS_PUBLIC)
|
|
|
|
|
|
|
|
res = self.client.post(self.delete_url, self.delete_data)
|
|
|
|
eq_(res.status_code, 302)
|
|
|
|
eq_(self.addon.versions.count(), 1)
|
|
|
|
eq_(Addon.objects.get(id=3615).status, amo.STATUS_PUBLIC)
|
|
|
|
|
|
|
|
def test_version_delete_status_unreviewd(self):
|
|
|
|
self._extra_version_and_file(amo.STATUS_BETA)
|
|
|
|
|
|
|
|
res = self.client.post(self.delete_url, self.delete_data)
|
2010-11-24 01:34:21 +03:00
|
|
|
eq_(res.status_code, 302)
|
2010-12-04 00:49:55 +03:00
|
|
|
eq_(self.addon.versions.count(), 1)
|
|
|
|
eq_(Addon.objects.get(id=3615).status, amo.STATUS_UNREVIEWED)
|
2010-11-24 01:34:21 +03:00
|
|
|
|
2010-12-04 00:49:55 +03:00
|
|
|
def test_user_can_disable_addon(self):
|
|
|
|
self.addon.update(status=amo.STATUS_PUBLIC,
|
2010-12-06 23:52:50 +03:00
|
|
|
disabled_by_user=False)
|
2010-12-04 00:49:55 +03:00
|
|
|
res = self.client.post(self.disable_url)
|
|
|
|
eq_(res.status_code, 302)
|
|
|
|
addon = Addon.objects.get(id=3615)
|
2010-12-06 23:52:50 +03:00
|
|
|
eq_(addon.disabled_by_user, True)
|
2010-12-04 00:49:55 +03:00
|
|
|
eq_(addon.status, amo.STATUS_PUBLIC)
|
|
|
|
|
|
|
|
entry = ActivityLog.objects.get()
|
2010-12-06 23:52:50 +03:00
|
|
|
eq_(entry.action, amo.LOG.USER_DISABLE.id)
|
2010-12-04 00:49:55 +03:00
|
|
|
msg = entry.to_string()
|
|
|
|
assert self.addon.name.__unicode__() in msg, ("Unexpected: %r" % msg)
|
|
|
|
|
|
|
|
def test_user_can_enable_addon(self):
|
|
|
|
self.addon.update(status=amo.STATUS_PUBLIC,
|
2010-12-06 23:52:50 +03:00
|
|
|
disabled_by_user=True)
|
2010-12-04 00:49:55 +03:00
|
|
|
res = self.client.get(self.enable_url)
|
|
|
|
eq_(res.status_code, 302)
|
|
|
|
addon = Addon.objects.get(id=3615)
|
2010-12-06 23:52:50 +03:00
|
|
|
eq_(addon.disabled_by_user, False)
|
2010-12-04 00:49:55 +03:00
|
|
|
eq_(addon.status, amo.STATUS_PUBLIC)
|
|
|
|
|
|
|
|
entry = ActivityLog.objects.get()
|
2010-12-06 23:52:50 +03:00
|
|
|
eq_(entry.action, amo.LOG.USER_ENABLE.id)
|
2010-12-04 00:49:55 +03:00
|
|
|
msg = entry.to_string()
|
|
|
|
assert unicode(self.addon.name) in msg, ("Unexpected: %r" % msg)
|
|
|
|
|
|
|
|
def test_unprivileged_user_cant_disable_addon(self):
|
2010-12-06 23:52:50 +03:00
|
|
|
self.addon.update(disabled_by_user=False)
|
2010-11-24 01:34:21 +03:00
|
|
|
self.client.logout()
|
|
|
|
res = self.client.post(self.disable_url)
|
|
|
|
eq_(res.status_code, 302)
|
2010-12-06 23:52:50 +03:00
|
|
|
eq_(Addon.objects.get(id=3615).disabled_by_user, False)
|
2010-12-04 00:49:55 +03:00
|
|
|
|
|
|
|
def test_non_owner_cant_disable_addon(self):
|
2010-12-06 23:52:50 +03:00
|
|
|
self.addon.update(disabled_by_user=False)
|
2010-12-04 00:49:55 +03:00
|
|
|
self.client.logout()
|
|
|
|
assert self.client.login(username='regular@mozilla.com',
|
|
|
|
password='password')
|
|
|
|
res = self.client.post(self.disable_url)
|
|
|
|
eq_(res.status_code, 403)
|
2010-12-06 23:52:50 +03:00
|
|
|
eq_(Addon.objects.get(id=3615).disabled_by_user, False)
|
2010-12-04 00:49:55 +03:00
|
|
|
|
|
|
|
def test_non_owner_cant_enable_addon(self):
|
2010-12-06 23:52:50 +03:00
|
|
|
self.addon.update(disabled_by_user=False)
|
2010-12-04 00:49:55 +03:00
|
|
|
self.client.logout()
|
|
|
|
assert self.client.login(username='regular@mozilla.com',
|
|
|
|
password='password')
|
|
|
|
res = self.client.get(self.enable_url)
|
|
|
|
eq_(res.status_code, 403)
|
2010-12-06 23:52:50 +03:00
|
|
|
eq_(Addon.objects.get(id=3615).disabled_by_user, False)
|
2010-11-24 01:34:21 +03:00
|
|
|
|
2010-12-04 00:49:55 +03:00
|
|
|
def test_show_disable_button(self):
|
2010-12-06 23:52:50 +03:00
|
|
|
self.addon.update(disabled_by_user=False)
|
2010-12-01 20:38:20 +03:00
|
|
|
res = self.client.get(self.url)
|
|
|
|
doc = pq(res.content)
|
|
|
|
assert doc('#modal-disable')
|
|
|
|
assert doc('#disable-addon')
|
2010-12-04 00:49:55 +03:00
|
|
|
assert not doc('#enable-addon')
|
2010-12-01 20:38:20 +03:00
|
|
|
|
2010-12-09 22:31:50 +03:00
|
|
|
def test_not_show_disable(self):
|
|
|
|
self.addon.update(status=amo.STATUS_DISABLED, disabled_by_user=False)
|
|
|
|
res = self.client.get(self.url)
|
|
|
|
doc = pq(res.content)
|
|
|
|
assert not doc('#modal-disable')
|
|
|
|
assert not doc('#disable-addon')
|
|
|
|
|
2010-12-04 00:49:55 +03:00
|
|
|
def test_show_enable_button(self):
|
2010-12-06 23:52:50 +03:00
|
|
|
self.addon.update(disabled_by_user=True)
|
2010-12-01 20:38:20 +03:00
|
|
|
res = self.client.get(self.url)
|
|
|
|
doc = pq(res.content)
|
2010-12-04 00:49:55 +03:00
|
|
|
a = doc('#enable-addon')
|
|
|
|
assert a, "Expected Enable addon link"
|
|
|
|
eq_(a.attr('href'), self.enable_url)
|
2010-12-01 20:38:20 +03:00
|
|
|
assert not doc('#modal-disable')
|
|
|
|
assert not doc('#disable-addon')
|
|
|
|
|
2010-12-07 00:37:23 +03:00
|
|
|
def test_cancel_wrong_status(self):
|
2010-12-20 23:47:01 +03:00
|
|
|
cancel_url = reverse('devhub.addons.cancel', args=['a3615'])
|
2010-12-07 00:37:23 +03:00
|
|
|
for status in amo.STATUS_CHOICES:
|
|
|
|
if status in amo.STATUS_UNDER_REVIEW:
|
|
|
|
continue
|
|
|
|
|
|
|
|
self.addon.update(status=status)
|
|
|
|
self.client.post(cancel_url)
|
|
|
|
eq_(Addon.objects.get(id=3615).status, status)
|
|
|
|
|
|
|
|
def test_cancel(self):
|
2010-12-20 23:47:01 +03:00
|
|
|
cancel_url = reverse('devhub.addons.cancel', args=['a3615'])
|
2010-12-17 04:11:05 +03:00
|
|
|
self.addon.update(status=amo.STATUS_LITE_AND_NOMINATED)
|
|
|
|
self.client.post(cancel_url)
|
|
|
|
eq_(Addon.objects.get(id=3615).status, amo.STATUS_LITE)
|
2010-12-07 00:37:23 +03:00
|
|
|
|
2010-12-17 04:11:05 +03:00
|
|
|
for status in (amo.STATUS_UNREVIEWED, amo.STATUS_NOMINATED):
|
|
|
|
self.addon.update(status=status)
|
2010-12-07 00:37:23 +03:00
|
|
|
self.client.post(cancel_url)
|
2010-12-17 04:11:05 +03:00
|
|
|
eq_(Addon.objects.get(id=3615).status, amo.STATUS_NULL)
|
2010-12-07 00:37:23 +03:00
|
|
|
|
|
|
|
def test_not_cancel(self):
|
|
|
|
self.client.logout()
|
2010-12-20 23:47:01 +03:00
|
|
|
cancel_url = reverse('devhub.addons.cancel', args=['a3615'])
|
2010-12-07 00:37:23 +03:00
|
|
|
eq_(self.addon.status, amo.STATUS_PUBLIC)
|
|
|
|
res = self.client.post(cancel_url)
|
|
|
|
eq_(res.status_code, 302)
|
|
|
|
eq_(Addon.objects.get(id=3615).status, amo.STATUS_PUBLIC)
|
|
|
|
|
|
|
|
def test_cancel_button(self):
|
|
|
|
for status in amo.STATUS_CHOICES:
|
|
|
|
if status not in amo.STATUS_UNDER_REVIEW:
|
|
|
|
continue
|
|
|
|
|
|
|
|
self.addon.update(status=status)
|
|
|
|
res = self.client.get(self.url)
|
|
|
|
doc = pq(res.content)
|
|
|
|
assert doc('#cancel-review')
|
|
|
|
assert doc('#modal-cancel')
|
|
|
|
|
|
|
|
def test_not_cancel_button(self):
|
|
|
|
for status in amo.STATUS_CHOICES:
|
|
|
|
if status in amo.STATUS_UNDER_REVIEW:
|
|
|
|
continue
|
|
|
|
|
|
|
|
self.addon.update(status=status)
|
|
|
|
res = self.client.get(self.url)
|
|
|
|
doc = pq(res.content)
|
|
|
|
assert not doc('#cancel-review')
|
|
|
|
assert not doc('#modal-cancel')
|
|
|
|
|
2010-12-10 23:00:05 +03:00
|
|
|
def test_purgatory_request_review(self):
|
|
|
|
self.addon.update(status=amo.STATUS_PURGATORY)
|
|
|
|
doc = pq(self.client.get(self.url).content)
|
|
|
|
buttons = doc('.version-status-actions form button').text()
|
|
|
|
eq_(buttons, 'Request Preliminary Review Request Full Review')
|
|
|
|
|
2011-01-06 03:08:03 +03:00
|
|
|
def test_add_version_modal(self):
|
|
|
|
r = self.client.get(self.url)
|
|
|
|
eq_(r.status_code, 200)
|
|
|
|
doc = pq(r.content)
|
|
|
|
# Make sure checkboxes are visible:
|
|
|
|
eq_(doc('input.platform').length, 4)
|
|
|
|
eq_(set([i.attrib['type'] for i in doc('input.platform')]),
|
|
|
|
set(['checkbox']))
|
|
|
|
|
2010-11-20 06:18:56 +03:00
|
|
|
|
2010-10-15 05:22:44 +04:00
|
|
|
class TestVersionEdit(test_utils.TestCase):
|
2010-10-20 21:40:20 +04:00
|
|
|
fixtures = ['base/apps', 'base/users', 'base/addon_3615',
|
2010-11-18 20:46:32 +03:00
|
|
|
'base/thunderbird', 'base/platforms']
|
2010-10-15 05:22:44 +04:00
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
assert self.client.login(username='del@icio.us', password='password')
|
|
|
|
self.addon = self.get_addon()
|
|
|
|
self.version = self.get_version()
|
|
|
|
self.url = reverse('devhub.versions.edit',
|
2010-12-20 23:47:01 +03:00
|
|
|
args=['a3615', self.version.id])
|
2010-10-20 21:40:20 +04:00
|
|
|
self.v1 = AppVersion(application_id=amo.FIREFOX.id, version='1.0')
|
|
|
|
self.v4 = AppVersion(application_id=amo.FIREFOX.id, version='4.0')
|
|
|
|
for v in self.v1, self.v4:
|
|
|
|
v.save()
|
2010-10-15 05:22:44 +04:00
|
|
|
|
|
|
|
def get_addon(self):
|
|
|
|
return Addon.objects.no_cache().get(id=3615)
|
|
|
|
|
|
|
|
def get_version(self):
|
|
|
|
return self.get_addon().current_version
|
|
|
|
|
2010-10-20 21:40:20 +04:00
|
|
|
def formset(self, *args, **kw):
|
|
|
|
defaults = {'approvalnotes': 'xxx'}
|
|
|
|
defaults.update(kw)
|
|
|
|
return formset(*args, **defaults)
|
|
|
|
|
2010-10-21 21:05:30 +04:00
|
|
|
|
|
|
|
class TestVersionEditDetails(TestVersionEdit):
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
super(TestVersionEditDetails, self).setUp()
|
|
|
|
ctx = self.client.get(self.url).context
|
|
|
|
compat = initial(ctx['compat_form'].forms[0])
|
|
|
|
files = initial(ctx['file_form'].forms[0])
|
|
|
|
self.initial = formset(compat, **formset(files, prefix='files'))
|
|
|
|
|
|
|
|
def formset(self, *args, **kw):
|
|
|
|
defaults = dict(self.initial)
|
|
|
|
defaults.update(kw)
|
|
|
|
return super(TestVersionEditDetails, self).formset(*args, **defaults)
|
|
|
|
|
2010-10-15 05:22:44 +04:00
|
|
|
def test_edit_notes(self):
|
2010-10-21 21:05:30 +04:00
|
|
|
d = self.formset(releasenotes='xx', approvalnotes='yy')
|
2010-10-20 21:40:20 +04:00
|
|
|
r = self.client.post(self.url, d)
|
2010-10-15 05:22:44 +04:00
|
|
|
eq_(r.status_code, 302)
|
|
|
|
version = self.get_version()
|
|
|
|
eq_(unicode(version.releasenotes), 'xx')
|
|
|
|
eq_(unicode(version.approvalnotes), 'yy')
|
2010-10-20 21:40:20 +04:00
|
|
|
|
2010-10-21 22:06:45 +04:00
|
|
|
def test_version_number_redirect(self):
|
|
|
|
url = self.url.replace(str(self.version.id), self.version.version)
|
|
|
|
r = self.client.get(url, follow=True)
|
|
|
|
self.assertRedirects(r, self.url)
|
|
|
|
|
2010-11-18 20:46:32 +03:00
|
|
|
def test_supported_platforms(self):
|
|
|
|
res = self.client.get(self.url)
|
|
|
|
choices = res.context['new_file_form'].fields['platform'].choices
|
2010-12-28 20:08:16 +03:00
|
|
|
taken = [f.platform_id for f in self.version.files.all()]
|
|
|
|
platforms = set(amo.SUPPORTED_PLATFORMS) - set(taken)
|
|
|
|
eq_(len(choices), len(platforms))
|
2010-11-18 20:46:32 +03:00
|
|
|
|
2010-12-24 01:05:31 +03:00
|
|
|
def test_can_upload(self):
|
|
|
|
self.version.files.all().delete()
|
2010-11-30 02:36:12 +03:00
|
|
|
r = self.client.get(self.url)
|
|
|
|
doc = pq(r.content)
|
|
|
|
assert doc('a.add-file')
|
|
|
|
|
2010-12-24 01:05:31 +03:00
|
|
|
def test_not_upload(self):
|
2010-11-30 02:36:12 +03:00
|
|
|
res = self.client.get(self.url)
|
|
|
|
doc = pq(res.content)
|
|
|
|
assert not doc('a.add-file')
|
|
|
|
|
2010-12-01 23:45:43 +03:00
|
|
|
def test_add(self):
|
|
|
|
res = self.client.get(self.url)
|
|
|
|
doc = pq(res.content)
|
|
|
|
assert res.context['compat_form'].extra_forms
|
|
|
|
assert doc('p.add-app')[0].attrib['class'] == 'add-app'
|
|
|
|
|
|
|
|
def test_add_not(self):
|
|
|
|
Application(id=52).save()
|
|
|
|
for id in [18, 52, 59, 60]:
|
|
|
|
av = AppVersion(application_id=id, version='1')
|
|
|
|
av.save()
|
|
|
|
ApplicationsVersions(application_id=id, min=av, max=av,
|
|
|
|
version=self.version).save()
|
|
|
|
|
|
|
|
res = self.client.get(self.url)
|
|
|
|
doc = pq(res.content)
|
|
|
|
assert not res.context['compat_form'].extra_forms
|
|
|
|
assert doc('p.add-app')[0].attrib['class'] == 'add-app hide'
|
|
|
|
|
2010-10-21 21:05:30 +04:00
|
|
|
|
2010-10-29 23:12:50 +04:00
|
|
|
class TestVersionEditSearchEngine(TestVersionEdit):
|
|
|
|
# https://bugzilla.mozilla.org/show_bug.cgi?id=605941
|
|
|
|
fixtures = ['base/apps', 'base/users',
|
2010-11-18 20:46:32 +03:00
|
|
|
'base/thunderbird', 'base/addon_4594_a9.json',
|
|
|
|
'base/platforms']
|
2010-10-29 23:12:50 +04:00
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
assert self.client.login(username='admin@mozilla.com',
|
|
|
|
password='password')
|
|
|
|
self.url = reverse('devhub.versions.edit',
|
2010-12-20 23:47:01 +03:00
|
|
|
args=['a4594', 42352])
|
2010-10-29 23:12:50 +04:00
|
|
|
|
|
|
|
def test_search_engine_edit(self):
|
|
|
|
dd = self.formset(prefix="files", releasenotes='xx',
|
|
|
|
approvalnotes='yy')
|
2010-11-10 04:59:19 +03:00
|
|
|
|
2010-10-29 23:12:50 +04:00
|
|
|
r = self.client.post(self.url, dd)
|
|
|
|
eq_(r.status_code, 302)
|
|
|
|
version = Addon.objects.no_cache().get(id=4594).current_version
|
|
|
|
eq_(unicode(version.releasenotes), 'xx')
|
|
|
|
eq_(unicode(version.approvalnotes), 'yy')
|
|
|
|
|
|
|
|
def test_no_compat(self):
|
|
|
|
r = self.client.get(self.url)
|
|
|
|
doc = pq(r.content)
|
|
|
|
assert not doc("#id_form-TOTAL_FORMS")
|
|
|
|
|
2010-11-30 02:36:12 +03:00
|
|
|
def test_no_upload(self):
|
|
|
|
r = self.client.get(self.url)
|
|
|
|
doc = pq(r.content)
|
|
|
|
assert not doc('a.add-file')
|
|
|
|
|
|
|
|
@mock.patch('versions.models.Version.is_allowed_upload')
|
|
|
|
def test_can_upload(self, allowed):
|
|
|
|
allowed.return_value = True
|
|
|
|
res = self.client.get(self.url)
|
|
|
|
doc = pq(res.content)
|
|
|
|
assert doc('a.add-file')
|
|
|
|
|
2010-10-29 23:12:50 +04:00
|
|
|
|
2010-10-21 21:05:30 +04:00
|
|
|
class TestVersionEditFiles(TestVersionEdit):
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
super(TestVersionEditFiles, self).setUp()
|
|
|
|
f = self.client.get(self.url).context['compat_form'].initial_forms[0]
|
|
|
|
self.compat = initial(f)
|
|
|
|
|
|
|
|
def formset(self, *args, **kw):
|
|
|
|
compat = formset(self.compat, initial_count=1)
|
|
|
|
compat.update(kw)
|
|
|
|
return super(TestVersionEditFiles, self).formset(*args, **compat)
|
|
|
|
|
2010-11-01 20:54:36 +03:00
|
|
|
def test_delete_file(self):
|
|
|
|
eq_(self.version.files.count(), 1)
|
|
|
|
forms = map(initial,
|
|
|
|
self.client.get(self.url).context['file_form'].forms)
|
|
|
|
forms[0]['DELETE'] = True
|
2010-11-02 20:45:45 +03:00
|
|
|
eq_(ActivityLog.objects.count(), 0)
|
2010-11-01 20:54:36 +03:00
|
|
|
r = self.client.post(self.url, self.formset(*forms, prefix='files'))
|
2010-11-02 20:45:45 +03:00
|
|
|
|
2010-12-09 02:53:34 +03:00
|
|
|
eq_(ActivityLog.objects.count(), 2)
|
2010-12-16 05:23:32 +03:00
|
|
|
log = ActivityLog.objects.order_by('created')[1]
|
2010-12-20 23:47:01 +03:00
|
|
|
eq_(log.to_string(), u'File delicious_bookmarks-2.1.072-fx.xpi deleted'
|
|
|
|
' from <a href="/en-US/firefox/addon/a3615'
|
2010-11-06 00:51:28 +03:00
|
|
|
'/versions/2.1.072">Version 2.1.072</a> of <a '
|
2010-12-20 23:47:01 +03:00
|
|
|
'href="/en-US/firefox/addon/a3615/">Delicious '
|
2010-12-15 04:55:42 +03:00
|
|
|
'Bookmarks</a>.')
|
2010-11-01 20:54:36 +03:00
|
|
|
eq_(r.status_code, 302)
|
|
|
|
eq_(self.version.files.count(), 0)
|
2010-11-11 04:03:11 +03:00
|
|
|
r = self.client.get(self.url)
|
|
|
|
eq_(r.status_code, 200)
|
2010-11-01 20:54:36 +03:00
|
|
|
|
2010-10-21 21:05:30 +04:00
|
|
|
def test_unique_platforms(self):
|
|
|
|
# Move the existing file to Linux.
|
|
|
|
f = self.version.files.get()
|
|
|
|
f.update(platform=Platform.objects.get(id=amo.PLATFORM_LINUX.id))
|
|
|
|
# And make a new file for Mac.
|
|
|
|
File.objects.create(version=self.version,
|
|
|
|
platform_id=amo.PLATFORM_MAC.id)
|
|
|
|
|
|
|
|
forms = map(initial,
|
|
|
|
self.client.get(self.url).context['file_form'].forms)
|
|
|
|
forms[1]['platform'] = forms[0]['platform']
|
|
|
|
r = self.client.post(self.url, self.formset(*forms, prefix='files'))
|
2010-11-10 04:59:19 +03:00
|
|
|
doc = pq(r.content)
|
|
|
|
assert doc('#id_files-0-platform')
|
2010-10-21 21:05:30 +04:00
|
|
|
eq_(r.status_code, 200)
|
|
|
|
eq_(r.context['file_form'].non_form_errors(),
|
|
|
|
['A platform can only be chosen once.'])
|
|
|
|
|
2010-12-21 01:45:02 +03:00
|
|
|
def test_all_platforms(self):
|
|
|
|
File.objects.create(version=self.version,
|
|
|
|
platform_id=amo.PLATFORM_MAC.id)
|
|
|
|
forms = self.client.get(self.url).context['file_form'].forms
|
|
|
|
forms = map(initial, forms)
|
|
|
|
res = self.client.post(self.url, self.formset(*forms, prefix='files'))
|
|
|
|
eq_(res.context['file_form'].non_form_errors()[0],
|
2010-12-23 03:55:15 +03:00
|
|
|
'The platfom All cannot be combined with specific platforms.')
|
2010-12-21 01:45:02 +03:00
|
|
|
|
|
|
|
def test_all_platforms_and_delete(self):
|
|
|
|
File.objects.create(version=self.version,
|
|
|
|
platform_id=amo.PLATFORM_MAC.id)
|
|
|
|
forms = self.client.get(self.url).context['file_form'].forms
|
|
|
|
forms = map(initial, forms)
|
|
|
|
# A test that we don't check the platform for deleted files.
|
|
|
|
forms[1]['DELETE'] = 1
|
|
|
|
self.client.post(self.url, self.formset(*forms, prefix='files'))
|
|
|
|
eq_(self.version.files.count(), 1)
|
|
|
|
|
2011-01-01 02:02:12 +03:00
|
|
|
def add_in_bsd(self):
|
|
|
|
f = self.version.files.get()
|
|
|
|
# The default file is All, which prevents the addition of more files.
|
|
|
|
f.update(platform=Platform.objects.get(id=amo.PLATFORM_MAC.id))
|
|
|
|
return File.objects.create(version=self.version,
|
|
|
|
platform_id=amo.PLATFORM_BSD.id)
|
|
|
|
|
|
|
|
def test_all_unsupported_platforms(self):
|
|
|
|
self.add_in_bsd()
|
|
|
|
forms = self.client.get(self.url).context['file_form'].forms
|
|
|
|
# Forms[0] is the form for the MAC and forms[1] is the form for the
|
|
|
|
# BSD file, which should have one extra platform in it.
|
|
|
|
eq_(len(forms[0].fields['platform'].choices), 4)
|
|
|
|
eq_(len(forms[1].fields['platform'].choices), 5)
|
|
|
|
|
|
|
|
def test_all_unsupported_platforms_unchange(self):
|
|
|
|
bsd = self.add_in_bsd()
|
|
|
|
forms = self.client.get(self.url).context['file_form'].forms
|
|
|
|
forms = map(initial, forms)
|
|
|
|
self.client.post(self.url, self.formset(*forms, prefix='files'))
|
|
|
|
eq_(File.objects.no_cache().get(pk=bsd.pk).platform_id,
|
|
|
|
amo.PLATFORM_BSD.id)
|
|
|
|
|
|
|
|
def test_all_unsupported_platforms_change(self):
|
|
|
|
bsd = self.add_in_bsd()
|
|
|
|
forms = self.client.get(self.url).context['file_form'].forms
|
|
|
|
forms = map(initial, forms)
|
|
|
|
forms[1]['platform'] = 2
|
|
|
|
self.client.post(self.url, self.formset(*forms, prefix='files'))
|
|
|
|
eq_(File.objects.no_cache().get(pk=bsd.pk).platform_id,
|
|
|
|
amo.PLATFORM_LINUX.id)
|
|
|
|
# Check you can't choose BSD anymore.
|
|
|
|
forms = self.client.get(self.url).context['file_form'].forms
|
|
|
|
eq_(len(forms[1].fields['platform'].choices), 4)
|
|
|
|
|
2011-01-06 03:08:03 +03:00
|
|
|
def test_add_file_modal(self):
|
|
|
|
r = self.client.get(self.url)
|
|
|
|
eq_(r.status_code, 200)
|
|
|
|
doc = pq(r.content)
|
|
|
|
# Make sure radio buttons are visible:
|
|
|
|
eq_(doc('input.platform').length, 3)
|
|
|
|
eq_(set([i.attrib['type'] for i in doc('input.platform')]),
|
|
|
|
set(['radio']))
|
|
|
|
|
2010-10-21 21:05:30 +04:00
|
|
|
|
2010-11-10 04:59:19 +03:00
|
|
|
class TestPlatformSearch(TestVersionEdit):
|
|
|
|
fixtures = ['base/apps', 'base/users',
|
|
|
|
'base/thunderbird', 'base/addon_4594_a9.json']
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
assert self.client.login(username='admin@mozilla.com',
|
|
|
|
password='password')
|
|
|
|
self.url = reverse('devhub.versions.edit',
|
2010-12-20 23:47:01 +03:00
|
|
|
args=['a4594', 42352])
|
2010-11-10 04:59:19 +03:00
|
|
|
self.version = Version.objects.get(id=42352)
|
|
|
|
self.file = self.version.files.all()[0]
|
|
|
|
for platform in amo.PLATFORMS:
|
|
|
|
k, _ = Platform.objects.get_or_create(id=platform)
|
|
|
|
|
|
|
|
def test_no_platform_search_engine(self):
|
|
|
|
response = self.client.get(self.url)
|
|
|
|
doc = pq(response.content)
|
|
|
|
assert not doc('#id_files-0-platform')
|
|
|
|
|
|
|
|
def test_changing_platform_search_engine(self):
|
|
|
|
dd = self.formset({'id': int(self.file.pk),
|
|
|
|
'platform': amo.PLATFORM_LINUX.id},
|
|
|
|
prefix='files', releasenotes='xx',
|
|
|
|
approvalnotes='yy')
|
|
|
|
response = self.client.post(self.url, dd)
|
|
|
|
eq_(response.status_code, 302)
|
|
|
|
uncached = Version.uncached.get(id=42352).files.all()[0]
|
|
|
|
eq_(amo.PLATFORM_ALL.id, uncached.platform.id)
|
|
|
|
|
|
|
|
|
2010-10-21 21:05:30 +04:00
|
|
|
class TestVersionEditCompat(TestVersionEdit):
|
|
|
|
|
|
|
|
def formset(self, *args, **kw):
|
|
|
|
defaults = formset(prefix='files')
|
|
|
|
defaults.update(kw)
|
|
|
|
return super(TestVersionEditCompat, self).formset(*args, **defaults)
|
|
|
|
|
2010-10-20 21:40:20 +04:00
|
|
|
def test_add_appversion(self):
|
|
|
|
f = self.client.get(self.url).context['compat_form'].initial_forms[0]
|
|
|
|
d = self.formset(initial(f), dict(application=18, min=28, max=29),
|
|
|
|
initial_count=1)
|
|
|
|
r = self.client.post(self.url, d)
|
|
|
|
eq_(r.status_code, 302)
|
|
|
|
apps = self.get_version().compatible_apps.keys()
|
2010-10-21 00:49:14 +04:00
|
|
|
eq_(sorted(apps), sorted([amo.FIREFOX, amo.THUNDERBIRD]))
|
2010-10-20 21:40:20 +04:00
|
|
|
|
|
|
|
def test_update_appversion(self):
|
|
|
|
av = self.version.apps.get()
|
|
|
|
eq_(av.min.version, '2.0')
|
|
|
|
eq_(av.max.version, '3.7a1pre')
|
|
|
|
f = self.client.get(self.url).context['compat_form'].initial_forms[0]
|
|
|
|
d = initial(f)
|
|
|
|
d.update(min=self.v1.id, max=self.v4.id)
|
|
|
|
r = self.client.post(self.url,
|
|
|
|
self.formset(d, initial_count=1))
|
|
|
|
eq_(r.status_code, 302)
|
|
|
|
av = self.version.apps.get()
|
|
|
|
eq_(av.min.version, '1.0')
|
|
|
|
eq_(av.max.version, '4.0')
|
|
|
|
|
|
|
|
def test_delete_appversion(self):
|
|
|
|
# Add thunderbird compat so we can delete firefox.
|
|
|
|
self.test_add_appversion()
|
|
|
|
f = self.client.get(self.url).context['compat_form']
|
|
|
|
d = map(initial, f.initial_forms)
|
|
|
|
d[0]['DELETE'] = True
|
|
|
|
r = self.client.post(self.url, self.formset(*d, initial_count=2))
|
|
|
|
eq_(r.status_code, 302)
|
|
|
|
apps = self.get_version().compatible_apps.keys()
|
|
|
|
eq_(apps, [amo.THUNDERBIRD])
|
|
|
|
|
|
|
|
def test_unique_apps(self):
|
|
|
|
f = self.client.get(self.url).context['compat_form'].initial_forms[0]
|
|
|
|
dupe = initial(f)
|
|
|
|
del dupe['id']
|
|
|
|
d = self.formset(initial(f), dupe, initial_count=1)
|
|
|
|
r = self.client.post(self.url, d)
|
|
|
|
eq_(r.status_code, 200)
|
|
|
|
# Because of how formsets work, the second form is expected to be a
|
|
|
|
# tbird version range. We got an error, so we're good.
|
|
|
|
|
|
|
|
def test_require_appversion(self):
|
|
|
|
old_av = self.version.apps.get()
|
|
|
|
f = self.client.get(self.url).context['compat_form'].initial_forms[0]
|
|
|
|
d = initial(f)
|
|
|
|
d['DELETE'] = True
|
|
|
|
r = self.client.post(self.url, self.formset(d, initial_count=1))
|
|
|
|
eq_(r.status_code, 200)
|
2010-10-30 04:26:52 +04:00
|
|
|
eq_(r.context['compat_form'].non_form_errors(),
|
|
|
|
['Need at least one compatible application.'])
|
2010-10-20 21:40:20 +04:00
|
|
|
eq_(self.version.apps.get(), old_av)
|
|
|
|
|
|
|
|
def test_proper_min_max(self):
|
|
|
|
f = self.client.get(self.url).context['compat_form'].initial_forms[0]
|
|
|
|
d = initial(f)
|
|
|
|
d['min'], d['max'] = d['max'], d['min']
|
|
|
|
r = self.client.post(self.url, self.formset(d, initial_count=1))
|
|
|
|
eq_(r.status_code, 200)
|
|
|
|
eq_(r.context['compat_form'].forms[0].non_field_errors(),
|
2010-10-28 22:04:20 +04:00
|
|
|
['Invalid version range.'])
|
2010-10-22 02:34:26 +04:00
|
|
|
|
2010-12-02 21:00:24 +03:00
|
|
|
def test_same_min_max(self):
|
|
|
|
f = self.client.get(self.url).context['compat_form'].initial_forms[0]
|
|
|
|
d = initial(f)
|
|
|
|
d['min'] = d['max']
|
|
|
|
r = self.client.post(self.url, self.formset(d, initial_count=1))
|
|
|
|
eq_(r.status_code, 302)
|
|
|
|
av = self.version.apps.all()[0]
|
|
|
|
eq_(av.min, av.max)
|
|
|
|
|
2010-10-22 02:34:26 +04:00
|
|
|
|
2010-11-17 05:15:54 +03:00
|
|
|
class TestSubmitBase(test_utils.TestCase):
|
2010-10-27 00:21:46 +04:00
|
|
|
fixtures = ['base/addon_3615', 'base/addon_5579', 'base/users']
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
assert self.client.login(username='del@icio.us', password='password')
|
|
|
|
|
2010-11-11 18:54:22 +03:00
|
|
|
def get_addon(self):
|
|
|
|
return Addon.objects.no_cache().get(pk=3615)
|
|
|
|
|
2010-11-18 02:28:49 +03:00
|
|
|
def get_step(self):
|
|
|
|
return SubmitStep.objects.get(addon=self.get_addon())
|
|
|
|
|
2010-11-17 05:15:54 +03:00
|
|
|
|
|
|
|
class TestSubmitStep1(TestSubmitBase):
|
|
|
|
|
2010-10-22 02:34:26 +04:00
|
|
|
def test_step1_submit(self):
|
2010-11-17 19:52:40 +03:00
|
|
|
response = self.client.get(reverse('devhub.submit.1'))
|
2010-10-25 20:17:14 +04:00
|
|
|
eq_(response.status_code, 200)
|
2010-11-11 00:53:09 +03:00
|
|
|
doc = pq(response.content)
|
2010-10-22 02:34:26 +04:00
|
|
|
assert len(response.context['agreement_text'])
|
2010-11-11 00:53:09 +03:00
|
|
|
links = doc('#agreement-container a')
|
|
|
|
assert len(links)
|
|
|
|
for ln in links:
|
|
|
|
href = ln.attrib['href']
|
|
|
|
assert not href.startswith('%'), (
|
2011-01-11 20:48:59 +03:00
|
|
|
"Looks like link %r to %r is still a placeholder" %
|
|
|
|
(href, ln.text))
|
2010-10-27 00:21:46 +04:00
|
|
|
|
2011-01-18 13:53:22 +03:00
|
|
|
|
2010-11-17 07:32:40 +03:00
|
|
|
class TestSubmitStep2(test_utils.TestCase):
|
2010-11-23 04:45:12 +03:00
|
|
|
# More tests in TestCreateAddon.
|
2010-11-17 07:32:40 +03:00
|
|
|
fixtures = ['base/users']
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
self.client.login(username='regular@mozilla.com', password='password')
|
|
|
|
|
|
|
|
def test_step_2_with_cookie(self):
|
2010-11-17 19:52:40 +03:00
|
|
|
r = self.client.post(reverse('devhub.submit.1'))
|
|
|
|
self.assertRedirects(r, reverse('devhub.submit.2'))
|
|
|
|
r = self.client.get(reverse('devhub.submit.2'))
|
2010-11-17 07:32:40 +03:00
|
|
|
eq_(r.status_code, 200)
|
|
|
|
|
|
|
|
def test_step_2_no_cookie(self):
|
|
|
|
# We require a cookie that gets set in step 1.
|
2010-11-17 19:52:40 +03:00
|
|
|
r = self.client.get(reverse('devhub.submit.2'), follow=True)
|
|
|
|
self.assertRedirects(r, reverse('devhub.submit.1'))
|
2010-11-17 07:32:40 +03:00
|
|
|
|
|
|
|
|
|
|
|
class TestSubmitStep3(test_utils.TestCase):
|
2010-12-21 03:51:09 +03:00
|
|
|
fixtures = ['base/addon_3615', 'base/addon_3615_categories',
|
|
|
|
'base/addon_5579', 'base/users']
|
2010-11-17 07:32:40 +03:00
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
super(TestSubmitStep3, self).setUp()
|
2011-01-06 23:36:36 +03:00
|
|
|
self.addon = self.get_addon()
|
2010-12-20 23:47:01 +03:00
|
|
|
self.url = reverse('devhub.submit.3', args=['a3615'])
|
2010-11-17 07:32:40 +03:00
|
|
|
assert self.client.login(username='del@icio.us', password='password')
|
|
|
|
SubmitStep.objects.create(addon_id=3615, step=3)
|
2010-11-23 06:03:07 +03:00
|
|
|
self._redis = mock_redis()
|
2010-12-07 00:55:41 +03:00
|
|
|
cron.build_reverse_name_lookup()
|
2010-11-23 06:03:07 +03:00
|
|
|
|
2010-12-10 06:51:46 +03:00
|
|
|
AddonCategory.objects.filter(addon=self.get_addon(),
|
|
|
|
category=Category.objects.get(id=23)).delete()
|
|
|
|
AddonCategory.objects.filter(addon=self.get_addon(),
|
|
|
|
category=Category.objects.get(id=24)).delete()
|
|
|
|
|
2011-01-06 23:36:36 +03:00
|
|
|
ctx = self.client.get(self.url).context['cat_form']
|
|
|
|
self.cat_initial = initial(ctx.initial_forms[0])
|
|
|
|
|
2010-12-10 06:51:46 +03:00
|
|
|
def get_addon(self):
|
|
|
|
return Addon.objects.no_cache().get(id=3615)
|
|
|
|
|
2010-11-23 06:03:07 +03:00
|
|
|
def tearDown(self):
|
|
|
|
reset_redis(self._redis)
|
2010-11-17 07:32:40 +03:00
|
|
|
|
2011-01-06 23:36:36 +03:00
|
|
|
def get_dict(self, **kw):
|
|
|
|
cat_initial = kw.pop('cat_initial', self.cat_initial)
|
|
|
|
fs = formset(cat_initial, initial_count=1)
|
|
|
|
result = {'name': 'Test name', 'slug': 'testname',
|
|
|
|
'description': 'desc', 'summary': 'Hello!'}
|
|
|
|
result.update(**kw)
|
|
|
|
result.update(fs)
|
|
|
|
return result
|
|
|
|
|
2010-12-29 19:17:27 +03:00
|
|
|
def test_submit_success(self):
|
2010-11-17 07:32:40 +03:00
|
|
|
r = self.client.get(self.url)
|
|
|
|
eq_(r.status_code, 200)
|
|
|
|
|
|
|
|
# Post and be redirected.
|
2011-01-06 23:36:36 +03:00
|
|
|
d = self.get_dict()
|
2010-11-17 07:32:40 +03:00
|
|
|
r = self.client.post(self.url, d)
|
|
|
|
eq_(r.status_code, 302)
|
|
|
|
eq_(SubmitStep.objects.get(addon=3615).step, 4)
|
|
|
|
|
2010-12-29 19:17:27 +03:00
|
|
|
addon = self.get_addon()
|
|
|
|
eq_(addon.name, 'Test name')
|
|
|
|
eq_(addon.slug, 'testname')
|
|
|
|
eq_(addon.description, 'desc')
|
|
|
|
eq_(addon.summary, 'Hello!')
|
2011-01-11 20:48:59 +03:00
|
|
|
# Test add-on log activity.
|
|
|
|
log_items = ActivityLog.objects.for_addons(addon)
|
|
|
|
assert not log_items.filter(action=amo.LOG.EDIT_DESCRIPTIONS.id), \
|
|
|
|
"Creating a description needn't be logged."
|
2010-12-29 19:17:27 +03:00
|
|
|
|
2010-12-07 00:55:41 +03:00
|
|
|
def test_submit_name_unique(self):
|
|
|
|
# Make sure name is unique.
|
2011-01-06 23:36:36 +03:00
|
|
|
r = self.client.post(self.url, self.get_dict(name='Cooliris'))
|
2010-12-07 00:55:41 +03:00
|
|
|
error = 'This add-on name is already in use. Please choose another.'
|
|
|
|
self.assertFormError(r, 'form', 'name', error)
|
|
|
|
|
|
|
|
def test_submit_name_unique_strip(self):
|
|
|
|
# Make sure we can't sneak in a name by adding a space or two.
|
2011-01-06 23:36:36 +03:00
|
|
|
r = self.client.post(self.url, self.get_dict(name=' Cooliris '))
|
2010-12-07 00:55:41 +03:00
|
|
|
error = 'This add-on name is already in use. Please choose another.'
|
|
|
|
self.assertFormError(r, 'form', 'name', error)
|
|
|
|
|
|
|
|
def test_submit_name_unique_case(self):
|
|
|
|
# Make sure unique names aren't case sensitive.
|
2011-01-06 23:36:36 +03:00
|
|
|
r = self.client.post(self.url, self.get_dict(name='cooliris'))
|
2010-12-07 00:55:41 +03:00
|
|
|
error = 'This add-on name is already in use. Please choose another.'
|
|
|
|
self.assertFormError(r, 'form', 'name', error)
|
|
|
|
|
2010-11-17 07:32:40 +03:00
|
|
|
def test_submit_name_required(self):
|
|
|
|
# Make sure name is required.
|
2011-01-06 23:36:36 +03:00
|
|
|
r = self.client.post(self.url, self.get_dict(name=''))
|
2010-11-17 07:32:40 +03:00
|
|
|
eq_(r.status_code, 200)
|
|
|
|
self.assertFormError(r, 'form', 'name', 'This field is required.')
|
|
|
|
|
|
|
|
def test_submit_name_length(self):
|
|
|
|
# Make sure the name isn't too long.
|
2011-01-06 23:36:36 +03:00
|
|
|
d = self.get_dict(name='a' * 51)
|
|
|
|
r = self.client.post(self.url, d)
|
2010-11-17 07:32:40 +03:00
|
|
|
eq_(r.status_code, 200)
|
|
|
|
error = 'Ensure this value has at most 50 characters (it has 51).'
|
|
|
|
self.assertFormError(r, 'form', 'name', error)
|
|
|
|
|
|
|
|
def test_submit_slug_invalid(self):
|
|
|
|
# Submit an invalid slug.
|
2011-01-06 23:36:36 +03:00
|
|
|
d = self.get_dict(slug='slug!!! aksl23%%')
|
2010-11-17 07:32:40 +03:00
|
|
|
r = self.client.post(self.url, d)
|
|
|
|
eq_(r.status_code, 200)
|
|
|
|
self.assertFormError(r, 'form', 'slug', "Enter a valid 'slug' " +
|
|
|
|
"consisting of letters, numbers, underscores or hyphens.")
|
|
|
|
|
|
|
|
def test_submit_slug_required(self):
|
|
|
|
# Make sure the slug is required.
|
2011-01-06 23:36:36 +03:00
|
|
|
r = self.client.post(self.url, self.get_dict(slug=''))
|
2010-11-17 07:32:40 +03:00
|
|
|
eq_(r.status_code, 200)
|
|
|
|
self.assertFormError(r, 'form', 'slug', 'This field is required.')
|
|
|
|
|
|
|
|
def test_submit_summary_required(self):
|
|
|
|
# Make sure summary is required.
|
2011-01-06 23:36:36 +03:00
|
|
|
r = self.client.post(self.url, self.get_dict(summary=''))
|
2010-11-17 07:32:40 +03:00
|
|
|
eq_(r.status_code, 200)
|
|
|
|
self.assertFormError(r, 'form', 'summary', 'This field is required.')
|
|
|
|
|
|
|
|
def test_submit_summary_length(self):
|
|
|
|
# Summary is too long.
|
2011-01-06 23:36:36 +03:00
|
|
|
r = self.client.post(self.url, self.get_dict(summary='a' * 251))
|
2010-11-17 07:32:40 +03:00
|
|
|
eq_(r.status_code, 200)
|
|
|
|
error = 'Ensure this value has at most 250 characters (it has 251).'
|
|
|
|
self.assertFormError(r, 'form', 'summary', error)
|
|
|
|
|
2010-12-10 06:51:46 +03:00
|
|
|
def test_submit_categories_required(self):
|
2011-01-06 23:36:36 +03:00
|
|
|
del self.cat_initial['categories']
|
|
|
|
r = self.client.post(self.url,
|
|
|
|
self.get_dict(cat_initial=self.cat_initial))
|
|
|
|
eq_(r.context['cat_form'].errors[0]['categories'],
|
|
|
|
['This field is required.'])
|
2010-12-10 06:51:46 +03:00
|
|
|
|
|
|
|
def test_submit_categories_max(self):
|
2011-01-06 23:36:36 +03:00
|
|
|
eq_(amo.MAX_CATEGORIES, 2)
|
|
|
|
self.cat_initial['categories'] = [22, 23, 24]
|
|
|
|
r = self.client.post(self.url,
|
|
|
|
self.get_dict(cat_initial=self.cat_initial))
|
|
|
|
eq_(r.context['cat_form'].errors[0]['categories'],
|
|
|
|
['You can have only 2 categories.'])
|
2010-12-10 06:51:46 +03:00
|
|
|
|
|
|
|
def test_submit_categories_add(self):
|
2011-01-06 23:36:36 +03:00
|
|
|
eq_([c.id for c in self.get_addon().all_categories], [22])
|
|
|
|
self.cat_initial['categories'] = [22, 23]
|
2011-01-13 01:27:31 +03:00
|
|
|
|
|
|
|
self.client.post(self.url, self.get_dict())
|
|
|
|
|
|
|
|
addon_cats = self.get_addon().categories.values_list('id', flat=True)
|
|
|
|
eq_(sorted(addon_cats), [22, 23])
|
2010-12-10 06:51:46 +03:00
|
|
|
|
|
|
|
def test_submit_categories_addandremove(self):
|
2011-01-06 23:36:36 +03:00
|
|
|
AddonCategory(addon=self.addon, category_id=23).save()
|
|
|
|
eq_([c.id for c in self.get_addon().all_categories], [22, 23])
|
2010-12-10 06:51:46 +03:00
|
|
|
|
2011-01-06 23:36:36 +03:00
|
|
|
self.cat_initial['categories'] = [22, 24]
|
|
|
|
self.client.post(self.url, self.get_dict(cat_initial=self.cat_initial))
|
|
|
|
category_ids_new = [c.id for c in self.get_addon().all_categories]
|
2010-12-10 06:51:46 +03:00
|
|
|
eq_(category_ids_new, [22, 24])
|
|
|
|
|
|
|
|
def test_submit_categories_remove(self):
|
2011-01-06 23:36:36 +03:00
|
|
|
c = Category.objects.get(id=23)
|
|
|
|
AddonCategory(addon=self.addon, category=c).save()
|
|
|
|
eq_([c.id for c in self.get_addon().all_categories], [22, 23])
|
2010-12-10 06:51:46 +03:00
|
|
|
|
2011-01-06 23:36:36 +03:00
|
|
|
self.cat_initial['categories'] = [22]
|
|
|
|
self.client.post(self.url, self.get_dict(cat_initial=self.cat_initial))
|
|
|
|
category_ids_new = [c.id for c in self.get_addon().all_categories]
|
2010-12-10 06:51:46 +03:00
|
|
|
eq_(category_ids_new, [22])
|
|
|
|
|
2010-12-07 05:35:24 +03:00
|
|
|
def test_check_version(self):
|
|
|
|
addon = Addon.objects.get(pk=3615)
|
|
|
|
|
|
|
|
r = self.client.get(self.url)
|
|
|
|
doc = pq(r.content)
|
|
|
|
version = doc("#current_version").val()
|
|
|
|
|
|
|
|
eq_(version, addon.current_version.version)
|
|
|
|
|
2010-11-19 22:32:13 +03:00
|
|
|
|
2010-12-10 03:36:00 +03:00
|
|
|
class TestSubmitStep4(TestSubmitBase):
|
|
|
|
|
|
|
|
def setUp(self):
|
2010-12-30 20:54:28 +03:00
|
|
|
self.old_addon_icon_url = settings.ADDON_ICON_URL
|
|
|
|
settings.ADDON_ICON_URL = "%s/%s/%s/images/addon_icon/%%d/%%s" % (
|
|
|
|
settings.STATIC_URL, settings.LANGUAGE_CODE, settings.DEFAULT_APP)
|
2010-12-10 03:36:00 +03:00
|
|
|
super(TestSubmitStep4, self).setUp()
|
|
|
|
SubmitStep.objects.create(addon_id=3615, step=5)
|
2010-12-20 23:47:01 +03:00
|
|
|
self.url = reverse('devhub.submit.4', args=['a3615'])
|
|
|
|
self.next_step = reverse('devhub.submit.5', args=['a3615'])
|
2011-01-12 02:53:58 +03:00
|
|
|
self.icon_upload = reverse('devhub.addons.upload_icon',
|
|
|
|
args=['a3615'])
|
|
|
|
self.preview_upload = reverse('devhub.addons.upload_preview',
|
|
|
|
args=['a3615'])
|
2010-12-10 03:36:00 +03:00
|
|
|
|
2010-12-30 20:54:28 +03:00
|
|
|
def tearDown(self):
|
|
|
|
settings.ADDON_ICON_URL = self.old_addon_icon_url
|
|
|
|
|
2010-12-10 03:36:00 +03:00
|
|
|
def test_get(self):
|
|
|
|
eq_(self.client.get(self.url).status_code, 200)
|
|
|
|
|
|
|
|
def test_post(self):
|
|
|
|
data = dict(icon_type='')
|
2010-12-31 04:02:31 +03:00
|
|
|
data_formset = self.formset_media(**data)
|
|
|
|
r = self.client.post(self.url, data_formset)
|
2010-12-10 03:36:00 +03:00
|
|
|
eq_(r.status_code, 302)
|
|
|
|
eq_(self.get_step().step, 5)
|
|
|
|
|
2010-12-31 04:02:31 +03:00
|
|
|
def formset_new_form(self, *args, **kw):
|
|
|
|
ctx = self.client.get(self.url).context
|
|
|
|
|
|
|
|
blank = initial(ctx['preview_form'].forms[-1])
|
|
|
|
blank.update(**kw)
|
|
|
|
return blank
|
|
|
|
|
|
|
|
def formset_media(self, *args, **kw):
|
|
|
|
kw.setdefault('initial_count', 0)
|
|
|
|
kw.setdefault('prefix', 'files')
|
|
|
|
|
|
|
|
fs = formset(*[a for a in args] + [self.formset_new_form()], **kw)
|
|
|
|
return dict([(k, '' if v is None else v) for k, v in fs.items()])
|
|
|
|
|
2010-12-10 03:36:00 +03:00
|
|
|
def test_edit_media_defaulticon(self):
|
|
|
|
data = dict(icon_type='')
|
2010-12-31 04:02:31 +03:00
|
|
|
data_formset = self.formset_media(**data)
|
|
|
|
|
|
|
|
self.client.post(self.url, data_formset)
|
2010-12-10 03:36:00 +03:00
|
|
|
|
|
|
|
addon = self.get_addon()
|
|
|
|
|
2011-01-12 22:06:00 +03:00
|
|
|
assert addon.get_icon_url(64).endswith('icons/default-64.png')
|
2010-12-10 03:36:00 +03:00
|
|
|
|
|
|
|
for k in data:
|
|
|
|
eq_(unicode(getattr(addon, k)), data[k])
|
|
|
|
|
|
|
|
def test_edit_media_preuploadedicon(self):
|
|
|
|
data = dict(icon_type='icon/appearance')
|
2010-12-31 04:02:31 +03:00
|
|
|
data_formset = self.formset_media(**data)
|
|
|
|
self.client.post(self.url, data_formset)
|
2010-12-10 03:36:00 +03:00
|
|
|
|
|
|
|
addon = self.get_addon()
|
|
|
|
|
|
|
|
eq_('/'.join(addon.get_icon_url(64).split('/')[-2:]),
|
|
|
|
'addon-icons/appearance-64.png')
|
|
|
|
|
|
|
|
for k in data:
|
|
|
|
eq_(unicode(getattr(addon, k)), data[k])
|
|
|
|
|
|
|
|
def test_edit_media_uploadedicon(self):
|
|
|
|
img = "%s/img/amo2009/tab-mozilla.png" % settings.MEDIA_ROOT
|
|
|
|
src_image = open(img, 'rb')
|
|
|
|
|
2011-01-12 02:53:58 +03:00
|
|
|
data = dict(upload_image=src_image)
|
|
|
|
|
|
|
|
response = self.client.post(self.icon_upload, data)
|
|
|
|
response_json = json.loads(response.content)
|
|
|
|
addon = self.get_addon()
|
|
|
|
|
|
|
|
# Now, save the form so it gets moved properly.
|
2010-12-10 03:36:00 +03:00
|
|
|
data = dict(icon_type='image/png',
|
2011-01-12 02:53:58 +03:00
|
|
|
icon_upload_hash=response_json['upload_hash'])
|
2010-12-31 04:02:31 +03:00
|
|
|
data_formset = self.formset_media(**data)
|
2011-01-12 02:53:58 +03:00
|
|
|
|
2011-01-18 13:53:22 +03:00
|
|
|
self.client.post(self.url, data_formset)
|
2010-12-10 03:36:00 +03:00
|
|
|
|
|
|
|
addon = self.get_addon()
|
2011-01-12 02:53:58 +03:00
|
|
|
|
2010-12-10 03:36:00 +03:00
|
|
|
eq_('/'.join(addon.get_icon_url(64).split('/')[-3:-1]),
|
|
|
|
'addon_icon/%s' % addon.id)
|
|
|
|
|
|
|
|
eq_(data['icon_type'], 'image/png')
|
|
|
|
|
|
|
|
# Check that it was actually uploaded
|
|
|
|
dirname = os.path.join(settings.ADDON_ICONS_PATH,
|
|
|
|
'%s' % (addon.id / 1000))
|
|
|
|
dest = os.path.join(dirname, '%s-32.png' % addon.id)
|
|
|
|
|
|
|
|
assert os.path.exists(dest)
|
|
|
|
|
|
|
|
eq_(Image.open(dest).size, (32, 12))
|
|
|
|
|
|
|
|
def test_edit_media_uploadedicon_noresize(self):
|
|
|
|
img = "%s/img/amo2009/notifications/error.png" % settings.MEDIA_ROOT
|
|
|
|
src_image = open(img, 'rb')
|
|
|
|
|
2011-01-12 02:53:58 +03:00
|
|
|
data = dict(upload_image=src_image)
|
|
|
|
|
|
|
|
response = self.client.post(self.icon_upload, data)
|
|
|
|
response_json = json.loads(response.content)
|
|
|
|
addon = self.get_addon()
|
|
|
|
|
|
|
|
# Now, save the form so it gets moved properly.
|
2010-12-10 03:36:00 +03:00
|
|
|
data = dict(icon_type='image/png',
|
2011-01-12 02:53:58 +03:00
|
|
|
icon_upload_hash=response_json['upload_hash'])
|
2010-12-31 04:02:31 +03:00
|
|
|
data_formset = self.formset_media(**data)
|
2010-12-10 03:36:00 +03:00
|
|
|
|
2011-01-18 13:53:22 +03:00
|
|
|
self.client.post(self.url, data_formset)
|
2010-12-10 03:36:00 +03:00
|
|
|
addon = self.get_addon()
|
|
|
|
|
|
|
|
eq_('/'.join(addon.get_icon_url(64).split('/')[-3:-1]),
|
|
|
|
'addon_icon/%s' % addon.id)
|
|
|
|
|
|
|
|
eq_(data['icon_type'], 'image/png')
|
|
|
|
|
|
|
|
# Check that it was actually uploaded
|
|
|
|
dirname = os.path.join(settings.ADDON_ICONS_PATH,
|
|
|
|
'%s' % (addon.id / 1000))
|
|
|
|
dest = os.path.join(dirname, '%s-64.png' % addon.id)
|
|
|
|
|
|
|
|
assert os.path.exists(dest)
|
|
|
|
|
|
|
|
eq_(Image.open(dest).size, (48, 48))
|
|
|
|
|
2010-12-10 22:52:26 +03:00
|
|
|
def test_client_lied(self):
|
|
|
|
filehandle = open(get_image_path('non-animated.gif'), 'rb')
|
2010-12-31 04:02:31 +03:00
|
|
|
|
2011-01-12 02:53:58 +03:00
|
|
|
data = {'upload_image': filehandle}
|
|
|
|
|
|
|
|
res = self.client.post(self.preview_upload, data)
|
|
|
|
response_json = json.loads(res.content)
|
|
|
|
|
|
|
|
eq_(response_json['errors'][0], u'Icons must be either PNG or JPG.')
|
2010-12-10 22:52:26 +03:00
|
|
|
|
|
|
|
def test_icon_animated(self):
|
|
|
|
filehandle = open(get_image_path('animated.png'), 'rb')
|
2011-01-12 02:53:58 +03:00
|
|
|
data = {'upload_image': filehandle}
|
|
|
|
|
|
|
|
res = self.client.post(self.preview_upload, data)
|
|
|
|
response_json = json.loads(res.content)
|
|
|
|
|
|
|
|
eq_(response_json['errors'][0], u'Icons cannot be animated.')
|
2010-12-10 22:52:26 +03:00
|
|
|
|
|
|
|
def test_icon_non_animated(self):
|
|
|
|
filehandle = open(get_image_path('non-animated.png'), 'rb')
|
|
|
|
data = {'icon_type': 'image/png', 'icon_upload': filehandle}
|
2010-12-31 04:02:31 +03:00
|
|
|
data_formset = self.formset_media(**data)
|
|
|
|
res = self.client.post(self.url, data_formset)
|
2010-12-10 22:52:26 +03:00
|
|
|
eq_(res.status_code, 302)
|
|
|
|
eq_(self.get_step().step, 5)
|
|
|
|
|
2011-01-18 13:53:22 +03:00
|
|
|
|
2010-11-18 02:28:49 +03:00
|
|
|
class TestSubmitStep5(TestSubmitBase):
|
2011-01-11 20:48:59 +03:00
|
|
|
"""License submission."""
|
2010-11-18 02:28:49 +03:00
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
super(TestSubmitStep5, self).setUp()
|
|
|
|
SubmitStep.objects.create(addon_id=3615, step=5)
|
2010-12-20 23:47:01 +03:00
|
|
|
self.url = reverse('devhub.submit.5', args=['a3615'])
|
|
|
|
self.next_step = reverse('devhub.submit.6', args=['a3615'])
|
2010-11-18 02:28:49 +03:00
|
|
|
License.objects.create(builtin=3, on_form=True)
|
|
|
|
|
|
|
|
def test_get(self):
|
|
|
|
eq_(self.client.get(self.url).status_code, 200)
|
|
|
|
|
|
|
|
def test_set_license(self):
|
|
|
|
r = self.client.post(self.url, {'builtin': 3})
|
|
|
|
self.assertRedirects(r, self.next_step)
|
|
|
|
eq_(self.get_addon().current_version.license.builtin, 3)
|
|
|
|
eq_(self.get_step().step, 6)
|
2011-01-11 20:48:59 +03:00
|
|
|
log_items = ActivityLog.objects.for_addons(self.get_addon())
|
|
|
|
assert not log_items.filter(action=amo.LOG.CHANGE_LICENSE.id), \
|
|
|
|
"Initial license choice:6 needn't be logged."
|
2010-11-18 02:28:49 +03:00
|
|
|
|
|
|
|
def test_license_error(self):
|
|
|
|
r = self.client.post(self.url, {'builtin': 4})
|
|
|
|
eq_(r.status_code, 200)
|
|
|
|
self.assertFormError(r, 'license_form', 'builtin',
|
|
|
|
'Select a valid choice. 4 is not one of '
|
|
|
|
'the available choices.')
|
|
|
|
eq_(self.get_step().step, 5)
|
|
|
|
|
|
|
|
def test_set_eula(self):
|
2010-12-03 01:28:25 +03:00
|
|
|
self.get_addon().update(eula=None, privacy_policy=None)
|
2010-11-18 02:28:49 +03:00
|
|
|
r = self.client.post(self.url, dict(builtin=3, has_eula=True,
|
|
|
|
eula='xxx'))
|
|
|
|
self.assertRedirects(r, self.next_step)
|
|
|
|
eq_(unicode(self.get_addon().eula), 'xxx')
|
|
|
|
eq_(self.get_step().step, 6)
|
|
|
|
|
2010-12-15 02:50:20 +03:00
|
|
|
def test_set_eula_nomsg(self):
|
|
|
|
"""
|
|
|
|
You should not get punished with a 500 for not writing your EULA...
|
2011-01-06 23:36:36 +03:00
|
|
|
but perhaps you should feel shame for lying to us. This test does not
|
2010-12-15 02:50:20 +03:00
|
|
|
test for shame.
|
|
|
|
"""
|
|
|
|
self.get_addon().update(eula=None, privacy_policy=None)
|
|
|
|
r = self.client.post(self.url, dict(builtin=3, has_eula=True))
|
|
|
|
self.assertRedirects(r, self.next_step)
|
|
|
|
eq_(self.get_step().step, 6)
|
|
|
|
|
2010-11-17 07:32:40 +03:00
|
|
|
|
2010-11-17 05:15:54 +03:00
|
|
|
class TestSubmitStep6(TestSubmitBase):
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
super(TestSubmitStep6, self).setUp()
|
|
|
|
SubmitStep.objects.create(addon_id=3615, step=6)
|
2010-12-20 23:47:01 +03:00
|
|
|
self.url = reverse('devhub.submit.6', args=['a3615'])
|
2010-11-17 05:15:54 +03:00
|
|
|
|
|
|
|
def test_get(self):
|
|
|
|
r = self.client.get(self.url)
|
2010-11-11 18:54:22 +03:00
|
|
|
eq_(r.status_code, 200)
|
|
|
|
|
2010-11-17 05:15:54 +03:00
|
|
|
def test_require_review_type(self):
|
|
|
|
r = self.client.post(self.url, {'dummy': 'text'})
|
2010-11-11 18:54:22 +03:00
|
|
|
eq_(r.status_code, 200)
|
|
|
|
self.assertFormError(r, 'review_type_form', 'review_type',
|
|
|
|
'A review type must be selected.')
|
|
|
|
|
2010-11-17 05:15:54 +03:00
|
|
|
def test_bad_review_type(self):
|
2010-11-11 18:54:22 +03:00
|
|
|
d = dict(review_type='jetsfool')
|
2010-11-17 05:15:54 +03:00
|
|
|
r = self.client.post(self.url, d)
|
2010-11-11 18:54:22 +03:00
|
|
|
eq_(r.status_code, 200)
|
|
|
|
self.assertFormError(r, 'review_type_form', 'review_type',
|
|
|
|
'Select a valid choice. jetsfool is not one of '
|
|
|
|
'the available choices.')
|
|
|
|
|
2010-11-17 05:15:54 +03:00
|
|
|
def test_prelim_review(self):
|
2010-11-11 18:54:22 +03:00
|
|
|
d = dict(review_type=amo.STATUS_UNREVIEWED)
|
2010-11-17 05:15:54 +03:00
|
|
|
r = self.client.post(self.url, d)
|
2010-11-11 18:54:22 +03:00
|
|
|
eq_(r.status_code, 302)
|
|
|
|
eq_(self.get_addon().status, amo.STATUS_UNREVIEWED)
|
2010-11-18 02:28:49 +03:00
|
|
|
assert_raises(SubmitStep.DoesNotExist, self.get_step)
|
2010-11-11 18:54:22 +03:00
|
|
|
|
2010-11-17 05:15:54 +03:00
|
|
|
def test_full_review(self):
|
2011-01-11 21:55:43 +03:00
|
|
|
self.get_addon().update(nomination_date=None)
|
2010-11-11 18:54:22 +03:00
|
|
|
d = dict(review_type=amo.STATUS_NOMINATED)
|
2010-11-17 05:15:54 +03:00
|
|
|
r = self.client.post(self.url, d)
|
2010-11-11 18:54:22 +03:00
|
|
|
eq_(r.status_code, 302)
|
2011-01-11 21:55:43 +03:00
|
|
|
addon = self.get_addon()
|
|
|
|
eq_(addon.status, amo.STATUS_NOMINATED)
|
2011-01-12 21:44:00 +03:00
|
|
|
assert_close_to_now(addon.nomination_date)
|
2010-11-18 02:28:49 +03:00
|
|
|
assert_raises(SubmitStep.DoesNotExist, self.get_step)
|
2010-11-17 05:15:54 +03:00
|
|
|
|
|
|
|
|
|
|
|
class TestSubmitStep7(TestSubmitBase):
|
2010-11-11 18:54:22 +03:00
|
|
|
|
2010-10-27 00:21:46 +04:00
|
|
|
def test_finish_submitting_addon(self):
|
|
|
|
addon = Addon.objects.get(
|
|
|
|
name__localized_string='Delicious Bookmarks')
|
|
|
|
eq_(addon.current_version.supported_platforms, [amo.PLATFORM_ALL])
|
|
|
|
|
2010-12-20 23:47:01 +03:00
|
|
|
response = self.client.get(reverse('devhub.submit.7', args=['a3615']))
|
2010-10-27 00:21:46 +04:00
|
|
|
eq_(response.status_code, 200)
|
|
|
|
doc = pq(response.content)
|
|
|
|
|
|
|
|
eq_(response.status_code, 200)
|
|
|
|
eq_(response.context['addon'].name.localized_string,
|
|
|
|
u"Delicious Bookmarks")
|
|
|
|
|
2010-12-20 23:47:01 +03:00
|
|
|
abs_url = settings.SITE_URL + "/en-US/firefox/addon/a3615/"
|
2010-10-27 00:21:46 +04:00
|
|
|
eq_(doc("a#submitted-addon-url").text().strip(), abs_url)
|
|
|
|
eq_(doc("a#submitted-addon-url").attr('href'),
|
2010-12-20 23:47:01 +03:00
|
|
|
"/en-US/firefox/addon/a3615/")
|
2010-10-27 00:21:46 +04:00
|
|
|
|
|
|
|
next_steps = doc(".done-next-steps li a")
|
|
|
|
|
|
|
|
# edit listing of freshly submitted add-on...
|
|
|
|
eq_(next_steps[0].attrib['href'],
|
|
|
|
reverse('devhub.addons.edit',
|
2010-12-20 23:47:01 +03:00
|
|
|
kwargs=dict(addon_id=addon.slug)))
|
2010-10-27 00:21:46 +04:00
|
|
|
|
|
|
|
# edit your developer profile...
|
|
|
|
eq_(next_steps[1].attrib['href'],
|
2010-12-20 23:47:01 +03:00
|
|
|
reverse('devhub.addons.profile', args=[addon.slug]))
|
2010-10-27 00:21:46 +04:00
|
|
|
|
2010-10-28 02:42:49 +04:00
|
|
|
# view wait times:
|
|
|
|
eq_(next_steps[3].attrib['href'],
|
|
|
|
"https://forums.addons.mozilla.org/viewforum.php?f=21")
|
|
|
|
|
2010-10-27 00:21:46 +04:00
|
|
|
def test_finish_submitting_platform_specific_addon(self):
|
|
|
|
# mac-only Add-on:
|
|
|
|
addon = Addon.objects.get(name__localized_string='Cooliris')
|
2010-11-11 18:54:22 +03:00
|
|
|
AddonUser.objects.create(user=UserProfile.objects.get(pk=55021),
|
|
|
|
addon=addon)
|
2010-12-20 23:47:01 +03:00
|
|
|
response = self.client.get(reverse('devhub.submit.7', args=['a5579']))
|
2010-10-27 00:21:46 +04:00
|
|
|
eq_(response.status_code, 200)
|
|
|
|
doc = pq(response.content)
|
|
|
|
next_steps = doc(".done-next-steps li a")
|
|
|
|
|
|
|
|
# upload more platform specific files...
|
|
|
|
eq_(next_steps[0].attrib['href'],
|
|
|
|
reverse('devhub.versions.edit', kwargs=dict(
|
2010-12-20 23:47:01 +03:00
|
|
|
addon_id=addon.slug,
|
2010-10-27 00:21:46 +04:00
|
|
|
version_id=addon.current_version.id)))
|
|
|
|
|
|
|
|
# edit listing of freshly submitted add-on...
|
|
|
|
eq_(next_steps[1].attrib['href'],
|
|
|
|
reverse('devhub.addons.edit',
|
2010-12-20 23:47:01 +03:00
|
|
|
kwargs=dict(addon_id=addon.slug)))
|
2010-10-29 02:20:37 +04:00
|
|
|
|
|
|
|
def test_finish_addon_for_prelim_review(self):
|
|
|
|
addon = Addon.objects.get(pk=3615)
|
|
|
|
addon.status = amo.STATUS_UNREVIEWED
|
|
|
|
addon.save()
|
|
|
|
|
2010-12-20 23:47:01 +03:00
|
|
|
response = self.client.get(reverse('devhub.submit.7', args=['a3615']))
|
2010-10-29 02:20:37 +04:00
|
|
|
eq_(response.status_code, 200)
|
|
|
|
doc = pq(response.content)
|
|
|
|
exp = 'Your add-on has been submitted to the Preliminary Review queue'
|
|
|
|
intro = doc('.addon-submission-process p').text()
|
|
|
|
assert exp in intro, ('Unexpected intro: %s' % intro.strip())
|
|
|
|
|
|
|
|
def test_finish_addon_for_full_review(self):
|
|
|
|
addon = Addon.objects.get(pk=3615)
|
2010-11-11 18:54:22 +03:00
|
|
|
addon.status = amo.STATUS_NOMINATED
|
2010-10-29 02:20:37 +04:00
|
|
|
addon.save()
|
|
|
|
|
2010-12-20 23:47:01 +03:00
|
|
|
response = self.client.get(reverse('devhub.submit.7', args=['a3615']))
|
2010-10-29 02:20:37 +04:00
|
|
|
eq_(response.status_code, 200)
|
|
|
|
doc = pq(response.content)
|
|
|
|
exp = 'Your add-on has been submitted to the Full Review queue'
|
|
|
|
intro = doc('.addon-submission-process p').text()
|
|
|
|
assert exp in intro, ('Unexpected intro: %s' % intro.strip())
|
2010-11-17 01:10:15 +03:00
|
|
|
|
2010-12-07 04:48:56 +03:00
|
|
|
def test_incomplete_addon_no_versions(self):
|
|
|
|
addon = Addon.objects.get(pk=3615)
|
|
|
|
addon.update(status=amo.STATUS_NULL)
|
|
|
|
addon.versions.all().delete()
|
2010-12-20 23:47:01 +03:00
|
|
|
r = self.client.get(reverse('devhub.submit.7', args=['a3615']),
|
2010-12-07 04:48:56 +03:00
|
|
|
follow=True)
|
2010-12-20 23:47:01 +03:00
|
|
|
self.assertRedirects(r, reverse('devhub.versions', args=['a3615']))
|
2010-12-07 04:48:56 +03:00
|
|
|
|
2011-01-19 00:39:11 +03:00
|
|
|
def test_link_to_activityfeed(self):
|
|
|
|
addon = Addon.objects.get(pk=3615)
|
|
|
|
r = self.client.get(reverse('devhub.submit.7', args=['a3615']),
|
|
|
|
follow=True)
|
|
|
|
doc = pq(r.content)
|
|
|
|
eq_(doc('.done-next-steps a').eq(2).attr('href'),
|
|
|
|
reverse('devhub.feed', args=[addon.slug]))
|
|
|
|
|
2010-12-31 01:05:56 +03:00
|
|
|
def test_display_non_ascii_url(self):
|
|
|
|
addon = Addon.objects.get(pk=3615)
|
2011-01-03 23:58:15 +03:00
|
|
|
u = 'フォクすけといっしょ'
|
|
|
|
addon.update(slug=u)
|
|
|
|
r = self.client.get(reverse('devhub.submit.7', args=[u]))
|
2010-12-31 01:05:56 +03:00
|
|
|
eq_(r.status_code, 200)
|
|
|
|
# The meta charset will always be utf-8.
|
|
|
|
doc = pq(r.content.decode('utf-8'))
|
|
|
|
eq_(doc('#submitted-addon-url').text(),
|
2011-01-03 23:58:15 +03:00
|
|
|
u'%s/en-US/firefox/addon/%s/' % (
|
|
|
|
settings.SITE_URL, u.decode('utf8')))
|
2010-12-31 01:05:56 +03:00
|
|
|
|
2010-11-17 01:10:15 +03:00
|
|
|
|
2010-11-30 01:18:05 +03:00
|
|
|
class TestResumeStep(TestSubmitBase):
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
super(TestResumeStep, self).setUp()
|
2010-12-20 23:47:01 +03:00
|
|
|
self.url = reverse('devhub.submit.resume', args=['a3615'])
|
2010-11-30 01:18:05 +03:00
|
|
|
|
|
|
|
def test_no_step_redirect(self):
|
|
|
|
r = self.client.get(self.url, follow=True)
|
2010-12-20 23:47:01 +03:00
|
|
|
self.assertRedirects(r, reverse('devhub.submit.7', args=['a3615']),
|
|
|
|
302)
|
2010-11-30 01:18:05 +03:00
|
|
|
|
|
|
|
def test_step_redirects(self):
|
|
|
|
SubmitStep.objects.create(addon_id=3615, step=1)
|
|
|
|
for i in xrange(3, 7):
|
|
|
|
SubmitStep.objects.filter(addon=self.get_addon()).update(step=i)
|
|
|
|
r = self.client.get(self.url, follow=True)
|
|
|
|
self.assertRedirects(r, reverse('devhub.submit.%s' % i,
|
2010-12-20 23:47:01 +03:00
|
|
|
args=['a3615']))
|
2010-11-30 01:18:05 +03:00
|
|
|
|
2011-01-18 13:53:22 +03:00
|
|
|
|
2010-11-17 05:15:54 +03:00
|
|
|
class TestSubmitSteps(test_utils.TestCase):
|
|
|
|
fixtures = ['base/apps', 'base/users', 'base/addon_3615']
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
assert self.client.login(username='del@icio.us', password='password')
|
|
|
|
|
2010-11-17 19:52:40 +03:00
|
|
|
def assert_linked(self, doc, numbers):
|
|
|
|
"""Check that the nth <li> in the steps list is a link."""
|
|
|
|
lis = doc('.submit-addon-progress li')
|
|
|
|
eq_(len(lis), 7)
|
|
|
|
for idx, li in enumerate(lis):
|
|
|
|
links = pq(li)('a')
|
|
|
|
if (idx + 1) in numbers:
|
|
|
|
eq_(len(links), 1)
|
|
|
|
else:
|
|
|
|
eq_(len(links), 0)
|
|
|
|
|
|
|
|
def assert_highlight(self, doc, num):
|
|
|
|
"""Check that the nth <li> is marked as .current."""
|
|
|
|
lis = doc('.submit-addon-progress li')
|
|
|
|
assert pq(lis[num - 1]).hasClass('current')
|
|
|
|
eq_(len(pq('.current', lis)), 1)
|
|
|
|
|
2010-11-17 05:15:54 +03:00
|
|
|
def test_step_1(self):
|
2010-11-17 19:52:40 +03:00
|
|
|
r = self.client.get(reverse('devhub.submit.1'))
|
2010-11-17 05:15:54 +03:00
|
|
|
eq_(r.status_code, 200)
|
|
|
|
|
|
|
|
def test_on_step_6(self):
|
|
|
|
# Hitting the step we're supposed to be on is a 200.
|
|
|
|
SubmitStep.objects.create(addon_id=3615, step=6)
|
2010-11-17 19:52:40 +03:00
|
|
|
r = self.client.get(reverse('devhub.submit.6',
|
2010-12-20 23:47:01 +03:00
|
|
|
args=['a3615']))
|
2010-11-17 05:15:54 +03:00
|
|
|
eq_(r.status_code, 200)
|
|
|
|
|
|
|
|
def test_skip_step_6(self):
|
|
|
|
# We get bounced back to step 3.
|
|
|
|
SubmitStep.objects.create(addon_id=3615, step=3)
|
2010-11-17 19:52:40 +03:00
|
|
|
r = self.client.get(reverse('devhub.submit.6',
|
2010-12-20 23:47:01 +03:00
|
|
|
args=['a3615']), follow=True)
|
|
|
|
self.assertRedirects(r, reverse('devhub.submit.3', args=['a3615']))
|
2010-11-17 05:15:54 +03:00
|
|
|
|
|
|
|
def test_all_done(self):
|
|
|
|
# There's no SubmitStep, so we must be done.
|
2010-11-17 19:52:40 +03:00
|
|
|
r = self.client.get(reverse('devhub.submit.6',
|
2010-12-20 23:47:01 +03:00
|
|
|
args=['a3615']), follow=True)
|
|
|
|
self.assertRedirects(r, reverse('devhub.submit.7', args=['a3615']))
|
2010-11-17 19:52:40 +03:00
|
|
|
|
|
|
|
def test_menu_step_1(self):
|
|
|
|
doc = pq(self.client.get(reverse('devhub.submit.1')).content)
|
|
|
|
self.assert_linked(doc, [1])
|
|
|
|
self.assert_highlight(doc, 1)
|
|
|
|
|
|
|
|
def test_menu_step_2(self):
|
2010-11-19 22:32:13 +03:00
|
|
|
self.client.post(reverse('devhub.submit.1'))
|
2010-11-17 19:52:40 +03:00
|
|
|
doc = pq(self.client.get(reverse('devhub.submit.2')).content)
|
|
|
|
self.assert_linked(doc, [1, 2])
|
|
|
|
self.assert_highlight(doc, 2)
|
|
|
|
|
|
|
|
def test_menu_step_3(self):
|
|
|
|
SubmitStep.objects.create(addon_id=3615, step=3)
|
2010-12-20 23:47:01 +03:00
|
|
|
url = reverse('devhub.submit.3', args=['a3615'])
|
2010-11-17 19:52:40 +03:00
|
|
|
doc = pq(self.client.get(url).content)
|
|
|
|
self.assert_linked(doc, [3])
|
|
|
|
self.assert_highlight(doc, 3)
|
|
|
|
|
|
|
|
def test_menu_step_3_from_6(self):
|
|
|
|
SubmitStep.objects.create(addon_id=3615, step=6)
|
2010-12-20 23:47:01 +03:00
|
|
|
url = reverse('devhub.submit.3', args=['a3615'])
|
2010-11-17 19:52:40 +03:00
|
|
|
doc = pq(self.client.get(url).content)
|
|
|
|
self.assert_linked(doc, [3, 4, 5, 6])
|
|
|
|
self.assert_highlight(doc, 3)
|
|
|
|
|
|
|
|
def test_menu_step_6(self):
|
|
|
|
SubmitStep.objects.create(addon_id=3615, step=6)
|
2010-12-20 23:47:01 +03:00
|
|
|
url = reverse('devhub.submit.6', args=['a3615'])
|
2010-11-17 19:52:40 +03:00
|
|
|
doc = pq(self.client.get(url).content)
|
|
|
|
self.assert_linked(doc, [3, 4, 5, 6])
|
|
|
|
self.assert_highlight(doc, 6)
|
|
|
|
|
|
|
|
def test_menu_step_7(self):
|
2010-12-20 23:47:01 +03:00
|
|
|
url = reverse('devhub.submit.7', args=['a3615'])
|
2010-11-17 19:52:40 +03:00
|
|
|
doc = pq(self.client.get(url).content)
|
|
|
|
self.assert_linked(doc, [])
|
|
|
|
self.assert_highlight(doc, 7)
|
2010-11-20 02:55:39 +03:00
|
|
|
|
|
|
|
|
2010-11-20 06:18:56 +03:00
|
|
|
class TestUpload(files.tests.UploadTest):
|
2010-11-20 05:46:12 +03:00
|
|
|
fixtures = ['base/apps', 'base/users']
|
2010-11-20 02:55:39 +03:00
|
|
|
|
|
|
|
def setUp(self):
|
2010-11-20 06:18:56 +03:00
|
|
|
super(TestUpload, self).setUp()
|
2010-11-20 02:55:39 +03:00
|
|
|
self.url = reverse('devhub.upload')
|
|
|
|
|
|
|
|
def post(self):
|
2011-01-22 03:12:44 +03:00
|
|
|
# Has to be a binary, non xpi file.
|
|
|
|
data = open(get_image_path('animated.png'), 'rb')
|
|
|
|
return self.client.post(self.url, {'upload': data})
|
2010-11-20 02:55:39 +03:00
|
|
|
|
|
|
|
def test_create_fileupload(self):
|
|
|
|
self.post()
|
2011-01-22 03:12:44 +03:00
|
|
|
|
|
|
|
upload = FileUpload.objects.get(name='animated.png')
|
|
|
|
eq_(upload.name, 'animated.png')
|
|
|
|
data = open(get_image_path('animated.png'), 'rb').read()
|
|
|
|
eq_(open(upload.path).read(), data)
|
2010-11-20 02:55:39 +03:00
|
|
|
|
|
|
|
def test_fileupload_user(self):
|
|
|
|
self.client.login(username='regular@mozilla.com', password='password')
|
|
|
|
self.post()
|
|
|
|
user = UserProfile.objects.get(email='regular@mozilla.com')
|
|
|
|
eq_(FileUpload.objects.get().user, user)
|
|
|
|
|
2011-01-26 23:54:59 +03:00
|
|
|
def test_fileupload_ascii_post(self):
|
2011-01-27 03:33:44 +03:00
|
|
|
path = 'apps/files/fixtures/files/jétpack.xpi'
|
|
|
|
data = open(os.path.join(settings.ROOT, path))
|
|
|
|
|
2011-01-26 23:54:59 +03:00
|
|
|
r = self.client.post(self.url, {'upload': data})
|
|
|
|
# If this is broke, we'll get a traceback.
|
|
|
|
eq_(r.status_code, 302)
|
|
|
|
|
2011-01-08 00:26:57 +03:00
|
|
|
@attr('validator')
|
2010-11-20 02:55:39 +03:00
|
|
|
def test_fileupload_validation(self):
|
|
|
|
self.post()
|
2011-01-22 03:12:44 +03:00
|
|
|
fu = FileUpload.objects.get(name='animated.png')
|
2010-12-21 01:23:33 +03:00
|
|
|
assert_no_validation_errors(fu)
|
2010-11-24 22:21:53 +03:00
|
|
|
assert fu.validation
|
|
|
|
validation = json.loads(fu.validation)
|
2011-01-22 03:12:44 +03:00
|
|
|
|
2010-11-20 02:55:39 +03:00
|
|
|
eq_(validation['success'], False)
|
2010-11-23 21:57:39 +03:00
|
|
|
# The current interface depends on this JSON structure:
|
2011-01-22 03:12:44 +03:00
|
|
|
eq_(validation['errors'], 2)
|
2010-11-23 21:57:39 +03:00
|
|
|
eq_(validation['warnings'], 0)
|
|
|
|
assert len(validation['messages'])
|
|
|
|
msg = validation['messages'][0]
|
|
|
|
assert 'uid' in msg, "Unexpected: %r" % msg
|
|
|
|
eq_(msg['type'], u'error')
|
2011-01-22 03:12:44 +03:00
|
|
|
eq_(msg['message'], u'The package is not of a recognized type.')
|
2010-11-23 21:57:39 +03:00
|
|
|
eq_(msg['description'], u'')
|
2010-11-20 02:55:39 +03:00
|
|
|
|
|
|
|
def test_redirect(self):
|
|
|
|
r = self.post()
|
|
|
|
upload = FileUpload.objects.get()
|
|
|
|
url = reverse('devhub.upload_detail', args=[upload.pk, 'json'])
|
|
|
|
self.assertRedirects(r, url)
|
2010-11-20 06:18:56 +03:00
|
|
|
|
|
|
|
|
2010-11-23 21:57:39 +03:00
|
|
|
class TestUploadDetail(files.tests.UploadTest):
|
2011-01-29 00:37:42 +03:00
|
|
|
fixtures = ['base/apps', 'base/appversion', 'base/users']
|
2010-11-23 21:57:39 +03:00
|
|
|
|
|
|
|
def post(self):
|
2011-01-22 03:12:44 +03:00
|
|
|
# Has to be a binary, non xpi file.
|
|
|
|
data = open(get_image_path('animated.png'), 'rb')
|
|
|
|
return self.client.post(reverse('devhub.upload'), {'upload': data})
|
2010-11-23 21:57:39 +03:00
|
|
|
|
2011-01-29 00:37:42 +03:00
|
|
|
def validation_ok(self):
|
|
|
|
return {
|
|
|
|
'errors': 0,
|
|
|
|
'success': True,
|
|
|
|
'warnings': 0,
|
|
|
|
'notices': 0,
|
|
|
|
'message_tree': {},
|
|
|
|
'messages': [],
|
|
|
|
'rejected': False
|
|
|
|
}
|
|
|
|
|
2011-01-08 00:26:57 +03:00
|
|
|
@attr('validator')
|
2010-11-23 21:57:39 +03:00
|
|
|
def test_detail_json(self):
|
|
|
|
self.post()
|
2011-01-22 03:12:44 +03:00
|
|
|
|
2010-11-23 21:57:39 +03:00
|
|
|
upload = FileUpload.objects.get()
|
|
|
|
r = self.client.get(reverse('devhub.upload_detail',
|
|
|
|
args=[upload.uuid, 'json']))
|
|
|
|
eq_(r.status_code, 200)
|
|
|
|
data = json.loads(r.content)
|
2010-12-21 01:23:33 +03:00
|
|
|
assert_no_validation_errors(data)
|
2010-11-23 21:57:39 +03:00
|
|
|
eq_(data['url'],
|
|
|
|
reverse('devhub.upload_detail', args=[upload.uuid, 'json']))
|
|
|
|
eq_(data['full_report_url'],
|
|
|
|
reverse('devhub.upload_detail', args=[upload.uuid]))
|
|
|
|
# We must have tiers
|
|
|
|
assert len(data['validation']['messages'])
|
|
|
|
msg = data['validation']['messages'][0]
|
|
|
|
eq_(msg['tier'], 1)
|
|
|
|
|
|
|
|
def test_detail_view(self):
|
|
|
|
self.post()
|
2011-01-22 03:12:44 +03:00
|
|
|
upload = FileUpload.objects.get(name='animated.png')
|
2010-11-23 21:57:39 +03:00
|
|
|
r = self.client.get(reverse('devhub.upload_detail',
|
|
|
|
args=[upload.uuid]))
|
|
|
|
eq_(r.status_code, 200)
|
|
|
|
doc = pq(r.content)
|
2011-01-22 03:12:44 +03:00
|
|
|
eq_(doc('header h2').text(), 'Validation Results for animated.png')
|
2010-11-23 21:57:39 +03:00
|
|
|
suite = doc('#addon-validator-suite')
|
|
|
|
eq_(suite.attr('data-validateurl'),
|
|
|
|
reverse('devhub.upload_detail', args=[upload.uuid, 'json']))
|
|
|
|
|
2011-01-29 00:37:42 +03:00
|
|
|
@mock.patch('devhub.tasks._validator')
|
|
|
|
def test_multi_app_addon_cannot_have_platforms(self, v):
|
|
|
|
v.return_value = json.dumps(self.validation_ok())
|
|
|
|
addon = os.path.join(settings.ROOT, 'apps', 'devhub', 'tests',
|
|
|
|
'addons', 'mobile-2.9.10-fx+fn.xpi')
|
|
|
|
with open(addon, 'rb') as f:
|
|
|
|
r = self.client.post(reverse('devhub.upload'),
|
|
|
|
{'upload': f})
|
|
|
|
eq_(r.status_code, 302)
|
|
|
|
upload = FileUpload.objects.get()
|
|
|
|
r = self.client.get(reverse('devhub.upload_detail',
|
|
|
|
args=[upload.uuid, 'json']))
|
|
|
|
eq_(r.status_code, 200)
|
|
|
|
data = json.loads(r.content)
|
|
|
|
eq_(data['new_platform_choices'], [
|
|
|
|
{'text': unicode(amo.PLATFORM_ALL.name), 'checked': True,
|
|
|
|
'value': amo.PLATFORM_ALL.id}])
|
|
|
|
|
|
|
|
@mock.patch('devhub.tasks._validator')
|
|
|
|
def test_new_platform_choices_for_mobile(self, v):
|
|
|
|
v.return_value = json.dumps(self.validation_ok())
|
|
|
|
addon = os.path.join(settings.ROOT, 'apps', 'devhub', 'tests',
|
|
|
|
'addons', 'mobile-0.1-fn.xpi')
|
|
|
|
with open(addon, 'rb') as f:
|
|
|
|
r = self.client.post(reverse('devhub.upload'),
|
|
|
|
{'upload': f})
|
|
|
|
eq_(r.status_code, 302)
|
|
|
|
upload = FileUpload.objects.get()
|
|
|
|
r = self.client.get(reverse('devhub.upload_detail',
|
|
|
|
args=[upload.uuid, 'json']))
|
|
|
|
eq_(r.status_code, 200)
|
|
|
|
data = json.loads(r.content)
|
|
|
|
eq_(data['new_platform_choices'], [
|
|
|
|
{'text': unicode(amo.PLATFORM_ALL.name), 'checked': True,
|
|
|
|
'value': amo.PLATFORM_ALL.id},
|
|
|
|
{'text': unicode(amo.PLATFORM_MAEMO.name),
|
|
|
|
'value': amo.PLATFORM_MAEMO.id},
|
|
|
|
{'text': unicode(amo.PLATFORM_ANDROID.name),
|
|
|
|
'value': amo.PLATFORM_ANDROID.id}])
|
|
|
|
|
|
|
|
@mock.patch('devhub.tasks._validator')
|
|
|
|
def test_unparsable_xpi(self, v):
|
|
|
|
v.return_value = json.dumps(self.validation_ok())
|
|
|
|
addon = os.path.join(settings.ROOT, 'apps', 'devhub', 'tests',
|
|
|
|
'addons', 'unopenable.xpi')
|
|
|
|
with open(addon, 'rb') as f:
|
|
|
|
r = self.client.post(reverse('devhub.upload'),
|
|
|
|
{'upload': f})
|
|
|
|
upload = FileUpload.objects.get()
|
|
|
|
r = self.client.get(reverse('devhub.upload_detail',
|
|
|
|
args=[upload.uuid, 'json']))
|
|
|
|
eq_(r.status_code, 200)
|
|
|
|
data = json.loads(r.content)
|
|
|
|
eq_(data['new_platform_choices'], None)
|
|
|
|
|
2010-11-23 21:57:39 +03:00
|
|
|
|
2010-12-07 20:45:26 +03:00
|
|
|
class TestUploadValidation(files.tests.UploadTest):
|
|
|
|
fixtures = ['base/apps', 'base/users',
|
|
|
|
'devhub/invalid-id-uploaded-xpi.json']
|
2010-12-08 01:48:09 +03:00
|
|
|
|
2010-12-07 20:45:26 +03:00
|
|
|
def test_no_html_in_messages(self):
|
|
|
|
upload = FileUpload.objects.get(name='invalid-id-20101206.xpi')
|
|
|
|
r = self.client.get(reverse('devhub.upload_detail',
|
|
|
|
args=[upload.uuid, 'json']))
|
|
|
|
eq_(r.status_code, 200)
|
|
|
|
data = json.loads(r.content)
|
|
|
|
msg = data['validation']['messages'][0]
|
|
|
|
eq_(msg['message'], 'The value of <em:id> is invalid.')
|
2010-12-11 03:28:17 +03:00
|
|
|
eq_(sorted(msg['context']),
|
|
|
|
[[u'<foo/>'], u'<em:description>...'])
|
2010-12-07 20:45:26 +03:00
|
|
|
|
|
|
|
|
2010-12-30 00:13:43 +03:00
|
|
|
class TestFileValidation(test_utils.TestCase):
|
|
|
|
fixtures = ['base/apps', 'base/users',
|
|
|
|
'devhub/addon-validation-1', 'base/platforms']
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
assert self.client.login(username='del@icio.us', password='password')
|
|
|
|
self.user = UserProfile.objects.get(email='del@icio.us')
|
|
|
|
self.file_validation = FileValidation.objects.get(pk=1)
|
|
|
|
self.file = self.file_validation.file
|
|
|
|
self.addon = self.file.version.addon
|
|
|
|
|
|
|
|
def test_version_list(self):
|
|
|
|
r = self.client.get(reverse('devhub.versions',
|
|
|
|
args=[self.addon.slug]))
|
|
|
|
eq_(r.status_code, 200)
|
|
|
|
doc = pq(r.content)
|
|
|
|
eq_(doc('td.file-validation a').text(),
|
|
|
|
'0 errors, 0 warnings')
|
|
|
|
eq_(doc('td.file-validation a').attr('href'),
|
|
|
|
reverse('devhub.file_validation',
|
|
|
|
args=[self.addon.slug, self.file.id]))
|
|
|
|
|
|
|
|
def test_results_page(self):
|
|
|
|
r = self.client.get(reverse('devhub.file_validation',
|
|
|
|
args=[self.addon.slug, self.file.id]),
|
|
|
|
follow=True)
|
|
|
|
eq_(r.status_code, 200)
|
|
|
|
eq_(r.context['addon'], self.addon)
|
|
|
|
doc = pq(r.content)
|
|
|
|
eq_(doc('header h2').text(),
|
|
|
|
u'Validation Results for searchaddon11102010-20101217.xml')
|
|
|
|
eq_(doc('#addon-validator-suite').attr('data-validateurl'),
|
|
|
|
reverse('devhub.json_file_validation',
|
|
|
|
args=[self.addon.slug, self.file.id]))
|
|
|
|
|
|
|
|
def test_only_dev_can_see_results(self):
|
|
|
|
self.client.logout()
|
|
|
|
assert self.client.login(username='regular@mozilla.com',
|
|
|
|
password='password')
|
|
|
|
r = self.client.get(reverse('devhub.file_validation',
|
|
|
|
args=[self.addon.slug, self.file.id]),
|
|
|
|
follow=True)
|
|
|
|
eq_(r.status_code, 403)
|
|
|
|
|
|
|
|
def test_only_dev_can_see_json_results(self):
|
|
|
|
self.client.logout()
|
|
|
|
assert self.client.login(username='regular@mozilla.com',
|
|
|
|
password='password')
|
|
|
|
r = self.client.post(reverse('devhub.json_file_validation',
|
|
|
|
args=[self.addon.slug, self.file.id]),
|
|
|
|
follow=True)
|
|
|
|
eq_(r.status_code, 403)
|
|
|
|
|
2011-01-28 17:33:28 +03:00
|
|
|
def test_editor_can_see_results(self):
|
|
|
|
self.client.logout()
|
|
|
|
assert self.client.login(username='editor@mozilla.com',
|
|
|
|
password='password')
|
|
|
|
r = self.client.get(reverse('devhub.file_validation',
|
|
|
|
args=[self.addon.slug, self.file.id]),
|
|
|
|
follow=True)
|
|
|
|
eq_(r.status_code, 200)
|
|
|
|
|
|
|
|
def test_editor_can_see_json_results(self):
|
|
|
|
self.client.logout()
|
|
|
|
assert self.client.login(username='editor@mozilla.com',
|
|
|
|
password='password')
|
|
|
|
r = self.client.post(reverse('devhub.json_file_validation',
|
|
|
|
args=[self.addon.slug, self.file.id]),
|
|
|
|
follow=True)
|
|
|
|
eq_(r.status_code, 200)
|
|
|
|
|
2010-12-30 00:13:43 +03:00
|
|
|
def test_no_html_in_messages(self):
|
|
|
|
r = self.client.post(reverse('devhub.json_file_validation',
|
|
|
|
args=[self.addon.slug, self.file.id]),
|
|
|
|
follow=True)
|
|
|
|
eq_(r.status_code, 200)
|
|
|
|
data = json.loads(r.content)
|
|
|
|
msg = data['validation']['messages'][0]
|
|
|
|
eq_(msg['message'], 'The value of <em:id> is invalid.')
|
|
|
|
eq_(sorted(msg['context']),
|
|
|
|
[[u'<foo/>'], u'<em:description>...'])
|
|
|
|
|
|
|
|
|
2010-12-30 01:30:08 +03:00
|
|
|
class TestValidateFile(files.tests.UploadTest):
|
|
|
|
fixtures = ['base/apps', 'base/users',
|
|
|
|
'devhub/addon-file-100456', 'base/platforms']
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
super(TestValidateFile, self).setUp()
|
|
|
|
assert self.client.login(username='del@icio.us', password='password')
|
|
|
|
self.user = UserProfile.objects.get(email='del@icio.us')
|
|
|
|
self.file = File.objects.get(pk=100456)
|
|
|
|
# Move the file into place as if it were a real file
|
|
|
|
os.makedirs(os.path.dirname(self.file.file_path))
|
|
|
|
shutil.copyfile(self.file_path('invalid-id-20101206.xpi'),
|
|
|
|
self.file.file_path)
|
|
|
|
self.addon = self.file.version.addon
|
|
|
|
|
2011-01-08 00:26:57 +03:00
|
|
|
@attr('validator')
|
2010-12-30 01:30:08 +03:00
|
|
|
def test_lazy_validate(self):
|
|
|
|
r = self.client.post(reverse('devhub.json_file_validation',
|
|
|
|
args=[self.addon.slug, self.file.id]),
|
|
|
|
follow=True)
|
|
|
|
eq_(r.status_code, 200)
|
|
|
|
data = json.loads(r.content)
|
|
|
|
assert_no_validation_errors(data)
|
|
|
|
msg = data['validation']['messages'][0]
|
|
|
|
eq_(msg['message'], 'The value of <em:id> is invalid.')
|
|
|
|
|
|
|
|
@mock.patch('devhub.tasks._validator')
|
|
|
|
def test_validator_errors(self, v):
|
|
|
|
v.side_effect = ValueError('catastrophic failure in amo-validator')
|
|
|
|
r = self.client.post(reverse('devhub.json_file_validation',
|
|
|
|
args=[self.addon.slug, self.file.id]),
|
|
|
|
follow=True)
|
|
|
|
eq_(r.status_code, 200)
|
|
|
|
data = json.loads(r.content)
|
|
|
|
eq_(data['validation'], '')
|
|
|
|
assert data['error'].endswith(
|
|
|
|
"ValueError: catastrophic failure in amo-validator\n"), (
|
|
|
|
'Unexpected error: ...%s' % data['error'][-50:-1])
|
|
|
|
|
|
|
|
|
2010-11-23 04:45:12 +03:00
|
|
|
def assert_json_error(request, field, msg):
|
|
|
|
eq_(request.status_code, 400)
|
|
|
|
eq_(request['Content-Type'], 'application/json')
|
|
|
|
field = '__all__' if field is None else field
|
|
|
|
content = json.loads(request.content)
|
|
|
|
assert field in content, '%r not in %r' % (field, content)
|
|
|
|
eq_(content[field], [msg])
|
|
|
|
|
|
|
|
|
2010-12-31 00:44:34 +03:00
|
|
|
def assert_json_field(request, field, msg):
|
|
|
|
eq_(request.status_code, 200)
|
|
|
|
eq_(request['Content-Type'], 'application/json')
|
|
|
|
content = json.loads(request.content)
|
|
|
|
assert field in content, '%r not in %r' % (field, content)
|
|
|
|
eq_(content[field], msg)
|
|
|
|
|
|
|
|
|
2010-11-23 03:40:53 +03:00
|
|
|
class UploadTest(files.tests.UploadTest, test_utils.TestCase):
|
2010-11-20 06:18:56 +03:00
|
|
|
fixtures = ['base/apps', 'base/users', 'base/addon_3615']
|
|
|
|
|
|
|
|
def setUp(self):
|
2010-11-23 03:40:53 +03:00
|
|
|
super(UploadTest, self).setUp()
|
2010-12-15 00:46:12 +03:00
|
|
|
self.upload = self.get_upload('extension.xpi')
|
2010-11-20 06:18:56 +03:00
|
|
|
self.addon = Addon.objects.get(id=3615)
|
|
|
|
self.version = self.addon.current_version
|
|
|
|
self.addon.update(guid='guid@xpi')
|
2010-12-21 01:45:02 +03:00
|
|
|
if not Platform.objects.filter(id=amo.PLATFORM_MAC.id):
|
|
|
|
Platform.objects.create(id=amo.PLATFORM_MAC.id)
|
2010-11-20 06:18:56 +03:00
|
|
|
assert self.client.login(username='del@icio.us', password='password')
|
|
|
|
|
2010-11-23 03:40:53 +03:00
|
|
|
|
|
|
|
class TestVersionAddFile(UploadTest):
|
2010-12-21 01:45:02 +03:00
|
|
|
fixtures = ['base/apps', 'base/users',
|
|
|
|
'base/addon_3615', 'base/platforms']
|
2010-11-23 03:40:53 +03:00
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
super(TestVersionAddFile, self).setUp()
|
|
|
|
self.version.update(version='0.1')
|
|
|
|
self.url = reverse('devhub.versions.add_file',
|
2010-12-20 23:47:01 +03:00
|
|
|
args=[self.addon.slug, self.version.id])
|
2010-11-23 03:40:53 +03:00
|
|
|
|
2010-12-21 01:45:02 +03:00
|
|
|
files = self.version.files.all()[0]
|
|
|
|
files.platform_id = amo.PLATFORM_LINUX.id
|
|
|
|
files.save()
|
|
|
|
|
2011-01-06 03:08:03 +03:00
|
|
|
def post(self, platform=amo.PLATFORM_MAC):
|
|
|
|
return self.client.post(self.url, dict(upload=self.upload.pk,
|
|
|
|
platform=platform.id))
|
|
|
|
|
2010-11-20 06:18:56 +03:00
|
|
|
def test_guid_matches(self):
|
|
|
|
self.addon.update(guid='something.different')
|
|
|
|
r = self.post()
|
2011-01-11 01:22:01 +03:00
|
|
|
assert_json_error(r, None, "UUID doesn't match add-on.")
|
2010-11-20 06:18:56 +03:00
|
|
|
|
|
|
|
def test_version_matches(self):
|
|
|
|
self.version.update(version='2.0')
|
|
|
|
r = self.post()
|
2010-11-23 04:45:12 +03:00
|
|
|
assert_json_error(r, None, "Version doesn't match")
|
2010-11-20 06:18:56 +03:00
|
|
|
|
|
|
|
def test_platform_limits(self):
|
2010-12-21 01:45:02 +03:00
|
|
|
r = self.post(platform=amo.PLATFORM_BSD)
|
2010-11-23 04:45:12 +03:00
|
|
|
assert_json_error(r, 'platform',
|
2010-11-20 06:18:56 +03:00
|
|
|
'Select a valid choice. That choice is not '
|
|
|
|
'one of the available choices.')
|
|
|
|
|
2010-12-28 20:08:16 +03:00
|
|
|
def test_platform_choices(self):
|
|
|
|
url = reverse('devhub.versions.edit',
|
|
|
|
args=[self.addon.slug, self.version.id])
|
|
|
|
r = self.client.get(url)
|
|
|
|
form = r.context['new_file_form']
|
|
|
|
platform = self.version.files.get().platform_id
|
|
|
|
choices = form.fields['platform'].choices
|
2011-01-12 00:20:16 +03:00
|
|
|
# User cannot upload existing platforms:
|
2010-12-28 20:08:16 +03:00
|
|
|
assert platform not in dict(choices), choices
|
2011-01-12 00:20:16 +03:00
|
|
|
# User cannot upload platform=ALL when platform files exist.
|
|
|
|
assert amo.PLATFORM_ALL.id not in dict(choices), choices
|
|
|
|
|
|
|
|
def test_platform_choices_when_no_files(self):
|
|
|
|
all_choices = amo.SUPPORTED_PLATFORMS.values()
|
|
|
|
self.version.files.all().delete()
|
|
|
|
url = reverse('devhub.versions.edit',
|
|
|
|
args=[self.addon.slug, self.version.id])
|
|
|
|
r = self.client.get(url)
|
|
|
|
form = r.context['new_file_form']
|
|
|
|
eq_(sorted(dict(form.fields['platform'].choices).keys()),
|
|
|
|
sorted([p.id for p in all_choices]))
|
2010-12-28 20:08:16 +03:00
|
|
|
|
2010-11-20 06:18:56 +03:00
|
|
|
def test_type_matches(self):
|
|
|
|
self.addon.update(type=amo.ADDON_THEME)
|
|
|
|
r = self.post()
|
2010-11-23 04:45:12 +03:00
|
|
|
assert_json_error(r, None, "<em:type> doesn't match add-on")
|
2010-11-20 06:18:56 +03:00
|
|
|
|
|
|
|
def test_file_platform(self):
|
|
|
|
# Check that we're creating a new file with the requested platform.
|
|
|
|
qs = self.version.files
|
|
|
|
eq_(len(qs.all()), 1)
|
|
|
|
assert not qs.filter(platform=amo.PLATFORM_MAC.id)
|
|
|
|
self.post()
|
|
|
|
eq_(len(qs.all()), 2)
|
|
|
|
assert qs.get(platform=amo.PLATFORM_MAC.id)
|
|
|
|
|
|
|
|
def test_upload_not_found(self):
|
|
|
|
r = self.client.post(self.url, dict(upload='xxx',
|
|
|
|
platform=amo.PLATFORM_MAC.id))
|
2010-11-23 04:45:12 +03:00
|
|
|
assert_json_error(r, 'upload',
|
2010-11-20 06:18:56 +03:00
|
|
|
'There was an error with your upload. '
|
|
|
|
'Please try again.')
|
|
|
|
|
2010-12-10 02:38:43 +03:00
|
|
|
@mock.patch('versions.models.Version.is_allowed_upload')
|
|
|
|
def test_cant_upload(self, allowed):
|
|
|
|
"""Test that if is_allowed_upload fails, the upload will fail."""
|
|
|
|
allowed.return_value = False
|
|
|
|
res = self.post()
|
|
|
|
assert_json_error(res, '__all__',
|
|
|
|
'You cannot upload any more files for this version.')
|
|
|
|
|
2010-11-20 06:18:56 +03:00
|
|
|
def test_success_html(self):
|
|
|
|
r = self.post()
|
|
|
|
eq_(r.status_code, 200)
|
|
|
|
new_file = self.version.files.get(platform=amo.PLATFORM_MAC.id)
|
|
|
|
eq_(r.context['form'].instance, new_file)
|
2010-11-23 03:40:53 +03:00
|
|
|
|
|
|
|
|
|
|
|
class TestAddVersion(UploadTest):
|
|
|
|
|
2011-01-06 03:08:03 +03:00
|
|
|
def post(self, platforms=[amo.PLATFORM_MAC]):
|
|
|
|
return self.client.post(self.url, dict(upload=self.upload.pk,
|
|
|
|
platforms=[p.id for p in
|
|
|
|
platforms]))
|
|
|
|
|
2010-11-23 03:40:53 +03:00
|
|
|
def setUp(self):
|
|
|
|
super(TestAddVersion, self).setUp()
|
2010-12-20 23:47:01 +03:00
|
|
|
self.url = reverse('devhub.versions.add', args=[self.addon.slug])
|
2010-11-23 03:40:53 +03:00
|
|
|
|
|
|
|
def test_unique_version_num(self):
|
|
|
|
self.version.update(version='0.1')
|
|
|
|
r = self.post()
|
2010-11-23 04:45:12 +03:00
|
|
|
assert_json_error(r, None, 'Version 0.1 already exists')
|
2010-11-23 03:40:53 +03:00
|
|
|
|
|
|
|
def test_success(self):
|
|
|
|
r = self.post()
|
|
|
|
version = self.addon.versions.get(version='0.1')
|
2010-12-31 00:44:34 +03:00
|
|
|
assert_json_field(r, 'url', reverse('devhub.versions.edit',
|
2010-12-20 23:47:01 +03:00
|
|
|
args=[self.addon.slug, version.id]))
|
2010-11-23 04:45:12 +03:00
|
|
|
|
2011-01-18 21:36:25 +03:00
|
|
|
def test_public(self):
|
|
|
|
self.post()
|
|
|
|
fle = File.objects.all().order_by("-created")[0]
|
|
|
|
eq_(fle.status, amo.STATUS_PUBLIC)
|
|
|
|
|
|
|
|
def test_not_public(self):
|
|
|
|
self.addon.update(trusted=False)
|
|
|
|
self.post()
|
|
|
|
fle = File.objects.all().order_by("-created")[0]
|
|
|
|
assert_not_equal(fle.status, amo.STATUS_PUBLIC)
|
|
|
|
|
2011-01-06 03:08:03 +03:00
|
|
|
def test_multiple_platforms(self):
|
|
|
|
r = self.post(platforms=[amo.PLATFORM_MAC,
|
|
|
|
amo.PLATFORM_LINUX])
|
|
|
|
eq_(r.status_code, 200)
|
|
|
|
version = self.addon.versions.get(version='0.1')
|
|
|
|
eq_(len(version.all_files), 2)
|
|
|
|
|
2010-11-23 04:45:12 +03:00
|
|
|
|
2010-12-16 23:01:15 +03:00
|
|
|
class TestVersionXSS(UploadTest):
|
|
|
|
|
|
|
|
def test_unique_version_num(self):
|
|
|
|
self.version.update(
|
|
|
|
version='<script>alert("Happy XSS-Xmas");</script>')
|
|
|
|
r = self.client.get(reverse('devhub.addons'))
|
|
|
|
eq_(r.status_code, 200)
|
|
|
|
assert '<script>alert' not in r.content
|
|
|
|
assert '<script>alert' in r.content
|
|
|
|
|
|
|
|
|
2010-11-23 04:45:12 +03:00
|
|
|
class TestCreateAddon(files.tests.UploadTest, test_utils.TestCase):
|
2011-01-04 21:13:24 +03:00
|
|
|
fixtures = ['base/apps', 'base/users', 'base/platforms']
|
2010-11-23 04:45:12 +03:00
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
super(TestCreateAddon, self).setUp()
|
2010-11-23 05:27:41 +03:00
|
|
|
self._redis = mock_redis()
|
2010-12-15 00:46:12 +03:00
|
|
|
self.upload = self.get_upload('extension.xpi')
|
2010-11-23 04:45:12 +03:00
|
|
|
self.url = reverse('devhub.submit.2')
|
|
|
|
assert self.client.login(username='regular@mozilla.com',
|
|
|
|
password='password')
|
|
|
|
self.client.post(reverse('devhub.submit.1'))
|
|
|
|
|
2010-11-23 05:27:41 +03:00
|
|
|
def tearDown(self):
|
|
|
|
reset_redis(self._redis)
|
|
|
|
|
2011-01-04 21:13:24 +03:00
|
|
|
def post(self, platforms=[amo.PLATFORM_ALL], expect_errors=False):
|
|
|
|
r = self.client.post(self.url,
|
|
|
|
dict(upload=self.upload.pk,
|
|
|
|
platforms=[p.id for p in platforms]),
|
|
|
|
follow=True)
|
|
|
|
eq_(r.status_code, 200)
|
|
|
|
if not expect_errors:
|
|
|
|
# Show any unexpected form errors.
|
|
|
|
if r.context and 'new_addon_form' in r.context:
|
|
|
|
eq_(r.context['new_addon_form'].errors.as_text(), '')
|
|
|
|
return r
|
2010-11-23 04:45:12 +03:00
|
|
|
|
|
|
|
def assert_json_error(self, *args):
|
|
|
|
UploadTest().assert_json_error(self, *args)
|
|
|
|
|
|
|
|
def test_unique_name(self):
|
|
|
|
ReverseNameLookup.add('xpi name', 34)
|
2011-01-04 21:13:24 +03:00
|
|
|
r = self.post(expect_errors=True)
|
|
|
|
eq_(r.context['new_addon_form'].non_field_errors(),
|
2010-11-09 05:43:19 +03:00
|
|
|
['This add-on name is already in use. '
|
|
|
|
'Please choose another.'])
|
2010-11-23 04:45:12 +03:00
|
|
|
|
|
|
|
def test_success(self):
|
|
|
|
eq_(Addon.objects.count(), 0)
|
|
|
|
r = self.post()
|
|
|
|
addon = Addon.objects.get()
|
2010-11-09 05:43:19 +03:00
|
|
|
self.assertRedirects(r, reverse('devhub.submit.3',
|
2010-12-20 23:47:01 +03:00
|
|
|
args=[addon.slug]))
|
2011-01-11 20:48:59 +03:00
|
|
|
log_items = ActivityLog.objects.for_addons(addon)
|
|
|
|
assert log_items.filter(action=amo.LOG.CREATE_ADDON.id), \
|
|
|
|
'New add-on creation never logged.'
|
2010-11-30 01:18:05 +03:00
|
|
|
|
2011-01-11 21:47:16 +03:00
|
|
|
def test_missing_platforms(self):
|
|
|
|
r = self.client.post(self.url, dict(upload=self.upload.pk))
|
|
|
|
eq_(r.status_code, 200)
|
|
|
|
eq_(r.context['new_addon_form'].errors.as_text(),
|
|
|
|
u'* platforms\n * This field is required.')
|
|
|
|
doc = pq(r.content)
|
|
|
|
eq_(doc('.platform ul.errorlist').text(),
|
|
|
|
'This field is required.')
|
|
|
|
|
2011-01-04 21:13:24 +03:00
|
|
|
def test_one_xpi_for_multiple_platforms(self):
|
|
|
|
eq_(Addon.objects.count(), 0)
|
|
|
|
r = self.post(platforms=[amo.PLATFORM_MAC,
|
|
|
|
amo.PLATFORM_LINUX])
|
|
|
|
addon = Addon.objects.get()
|
|
|
|
self.assertRedirects(r, reverse('devhub.submit.3',
|
|
|
|
args=[addon.slug]))
|
|
|
|
eq_(sorted([f.filename for f in addon.current_version.all_files]),
|
|
|
|
[u'xpi_name-0.1-linux.xpi', u'xpi_name-0.1-mac.xpi'])
|
|
|
|
|
2010-11-30 01:18:05 +03:00
|
|
|
|
|
|
|
class TestDeleteAddon(test_utils.TestCase):
|
|
|
|
fixtures = ['base/apps', 'base/users', 'base/addon_3615']
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
super(TestDeleteAddon, self).setUp()
|
2010-12-20 23:47:01 +03:00
|
|
|
self.url = reverse('devhub.addons.delete', args=['a3615'])
|
2010-11-30 01:18:05 +03:00
|
|
|
assert self.client.login(username='del@icio.us', password='password')
|
|
|
|
self.addon = Addon.objects.get(id=3615)
|
|
|
|
|
|
|
|
def post(self, *args, **kw):
|
|
|
|
r = self.client.post(self.url, dict(*args, **kw))
|
|
|
|
eq_(r.status_code, 302)
|
|
|
|
return r
|
|
|
|
|
|
|
|
def test_bad_password(self):
|
|
|
|
r = self.post(password='turd')
|
|
|
|
eq_(r.context['title'],
|
|
|
|
'Password was incorrect. Add-on was not deleted.')
|
|
|
|
eq_(Addon.objects.count(), 1)
|
|
|
|
|
|
|
|
def test_success(self):
|
|
|
|
r = self.post(password='password')
|
|
|
|
eq_(r.context['title'], 'Add-on deleted.')
|
|
|
|
eq_(Addon.objects.count(), 0)
|
|
|
|
self.assertRedirects(r, reverse('devhub.addons'))
|
2010-12-10 22:21:26 +03:00
|
|
|
|
|
|
|
|
|
|
|
class TestRequestReview(test_utils.TestCase):
|
2010-12-30 00:57:50 +03:00
|
|
|
fixtures = ['base/users', 'base/platforms']
|
2010-12-10 22:21:26 +03:00
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
self.addon = Addon.objects.create(type=1, name='xxx')
|
2010-12-30 00:15:23 +03:00
|
|
|
self.version = Version.objects.create(addon=self.addon)
|
2010-12-30 00:57:50 +03:00
|
|
|
self.file = File.objects.create(version=self.version,
|
|
|
|
platform_id=amo.PLATFORM_ALL.id)
|
2010-12-20 23:47:01 +03:00
|
|
|
self.redirect_url = reverse('devhub.versions', args=[self.addon.slug])
|
2010-12-10 22:21:26 +03:00
|
|
|
self.lite_url = reverse('devhub.request-review',
|
2010-12-20 23:47:01 +03:00
|
|
|
args=[self.addon.slug, amo.STATUS_LITE])
|
2010-12-10 22:21:26 +03:00
|
|
|
self.public_url = reverse('devhub.request-review',
|
2010-12-20 23:47:01 +03:00
|
|
|
args=[self.addon.slug, amo.STATUS_PUBLIC])
|
2010-12-10 22:21:26 +03:00
|
|
|
assert self.client.login(username='admin@mozilla.com',
|
|
|
|
password='password')
|
|
|
|
|
|
|
|
def get_addon(self):
|
|
|
|
return Addon.objects.get(id=self.addon.id)
|
|
|
|
|
|
|
|
def check(self, old_status, url, new_status):
|
|
|
|
self.addon.update(status=old_status)
|
|
|
|
r = self.client.post(url)
|
|
|
|
self.assertRedirects(r, self.redirect_url)
|
|
|
|
eq_(self.get_addon().status, new_status)
|
|
|
|
|
|
|
|
def check_400(self, url):
|
|
|
|
r = self.client.post(url)
|
|
|
|
eq_(r.status_code, 400)
|
|
|
|
|
|
|
|
def test_404(self):
|
|
|
|
bad_url = self.public_url.replace(str(amo.STATUS_PUBLIC), '0')
|
|
|
|
eq_(self.client.post(bad_url).status_code, 404)
|
|
|
|
|
|
|
|
def test_public(self):
|
|
|
|
self.addon.update(status=amo.STATUS_PUBLIC)
|
|
|
|
self.check_400(self.lite_url)
|
|
|
|
self.check_400(self.public_url)
|
|
|
|
|
|
|
|
def test_disabled_by_user_to_lite(self):
|
|
|
|
self.addon.update(disabled_by_user=True)
|
|
|
|
self.check_400(self.lite_url)
|
|
|
|
|
|
|
|
def test_disabled_by_admin(self):
|
|
|
|
self.addon.update(status=amo.STATUS_DISABLED)
|
|
|
|
self.check_400(self.lite_url)
|
|
|
|
|
|
|
|
def test_lite_to_lite(self):
|
|
|
|
self.addon.update(status=amo.STATUS_LITE)
|
|
|
|
self.check_400(self.lite_url)
|
|
|
|
|
|
|
|
def test_lite_to_public(self):
|
2011-01-11 00:00:24 +03:00
|
|
|
eq_(self.addon.nomination_date, None)
|
2010-12-10 22:21:26 +03:00
|
|
|
self.check(amo.STATUS_LITE, self.public_url,
|
|
|
|
amo.STATUS_LITE_AND_NOMINATED)
|
2011-01-11 00:00:24 +03:00
|
|
|
self.addon = Addon.objects.get(pk=self.addon.id)
|
2011-01-12 21:44:00 +03:00
|
|
|
assert_close_to_now(self.addon.nomination_date)
|
2010-12-10 22:21:26 +03:00
|
|
|
|
|
|
|
def test_purgatory_to_lite(self):
|
|
|
|
self.check(amo.STATUS_PURGATORY, self.lite_url, amo.STATUS_UNREVIEWED)
|
|
|
|
|
|
|
|
def test_purgatory_to_public(self):
|
2011-01-11 00:00:24 +03:00
|
|
|
eq_(self.addon.nomination_date, None)
|
|
|
|
self.check(amo.STATUS_PURGATORY, self.public_url,
|
|
|
|
amo.STATUS_NOMINATED)
|
|
|
|
self.addon = Addon.objects.get(pk=self.addon.id)
|
2011-01-12 21:44:00 +03:00
|
|
|
assert_close_to_now(self.addon.nomination_date)
|
2010-12-10 22:21:26 +03:00
|
|
|
|
|
|
|
def test_lite_and_nominated_to_public(self):
|
|
|
|
self.addon.update(status=amo.STATUS_LITE_AND_NOMINATED)
|
|
|
|
self.check_400(self.public_url)
|
|
|
|
|
|
|
|
def test_lite_and_nominated(self):
|
|
|
|
self.addon.update(status=amo.STATUS_LITE_AND_NOMINATED)
|
|
|
|
self.check_400(self.lite_url)
|
|
|
|
self.check_400(self.public_url)
|
2011-01-06 04:57:00 +03:00
|
|
|
|
|
|
|
|
|
|
|
class TestRedirects(test_utils.TestCase):
|
|
|
|
fixtures = ['base/apps', 'base/users', 'base/addon_3615']
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
self.base = reverse('devhub.index')
|
|
|
|
assert self.client.login(username='admin@mozilla.com',
|
|
|
|
password='password')
|
|
|
|
|
|
|
|
def test_edit(self):
|
|
|
|
url = self.base + 'addon/edit/3615'
|
|
|
|
r = self.client.get(url, follow=True)
|
|
|
|
self.assertRedirects(r, reverse('devhub.addons.edit', args=['a3615']),
|
|
|
|
301)
|
|
|
|
|
|
|
|
url = self.base + 'addon/edit/3615/'
|
|
|
|
r = self.client.get(url, follow=True)
|
|
|
|
self.assertRedirects(r, reverse('devhub.addons.edit', args=['a3615']),
|
|
|
|
301)
|
|
|
|
|
|
|
|
def test_status(self):
|
|
|
|
url = self.base + 'addon/status/3615'
|
|
|
|
r = self.client.get(url, follow=True)
|
|
|
|
self.assertRedirects(r, reverse('devhub.versions', args=['a3615']),
|
|
|
|
301)
|
|
|
|
|
|
|
|
def test_versions(self):
|
|
|
|
url = self.base + 'versions/3615'
|
|
|
|
r = self.client.get(url, follow=True)
|
|
|
|
self.assertRedirects(r, reverse('devhub.versions', args=['a3615']),
|
|
|
|
301)
|