This commit is contained in:
Andrew Williamson 2016-09-28 12:06:11 +01:00 коммит произвёл GitHub
Родитель aab1e8cfd8
Коммит 42b82a57c1
21 изменённых файлов: 312 добавлений и 1286 удалений

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

@ -39,9 +39,7 @@ class Command(BaseCommand):
def get_files(addon_guids): def get_files(addon_guids):
"""Return the list of files that need approval, given a list of GUIDs. """Return the list of files that need approval, given a list of GUIDs.
A file needs approval if: A file needs approval if it's unreviewed.
- it's unreviewed
- it's preliminary reviewed, but its addon is requesting a full review
""" """
# Get all the add-ons that have a GUID from the list, and which are either # Get all the add-ons that have a GUID from the list, and which are either
# reviewed or awaiting a review. # reviewed or awaiting a review.
@ -59,11 +57,7 @@ def get_files(addon_guids):
def approve_files(files_with_review_type): def approve_files(files_with_review_type):
"""Approve the files (and sign them). """Approve the files (and sign them).
A file will be fully approved if: A file will be fully approved if it's waiting for a full review
- it's waiting for a full review
- it's preliminary reviewed, and its addon is waiting for a full review
A file will be prelim approved if:
- it's waiting for a prelim review
""" """
for file_, review_type in files_with_review_type: for file_, review_type in files_with_review_type:
version = file_.version version = file_.version
@ -77,10 +71,6 @@ def approve_files(files_with_review_type):
# Already fully reviewed, or waiting for a full review. # Already fully reviewed, or waiting for a full review.
helper.handler.process_public() helper.handler.process_public()
log.info(u'File %s (addon %s) fully reviewed', file_.pk, addon.pk) log.info(u'File %s (addon %s) fully reviewed', file_.pk, addon.pk)
elif review_type == 'prelim':
# Already prelim reviewed, or waiting for a prelim review.
helper.handler.process_preliminary()
log.info(u'File %s (addon %s) prelim reviewed', file_.pk, addon.pk)
else: else:
log.info(u'File %s (addon %s) not reviewed: ' log.info(u'File %s (addon %s) not reviewed: '
u'addon status: %s, file status: %s', u'addon status: %s, file status: %s',
@ -88,17 +78,10 @@ def approve_files(files_with_review_type):
def get_review_type(file_): def get_review_type(file_):
"""Return 'full', 'prelim' or None depending on the file/addon status.""" """Return 'full' or None depending on the file/addon status."""
addon_status = file_.version.addon.status addon_status = file_.version.addon.status
if addon_status in [amo.STATUS_NOMINATED, amo.STATUS_LITE_AND_NOMINATED]: if addon_status == amo.STATUS_NOMINATED or (
# Add-on is waiting for a full review. addon_status == amo.STATUS_PUBLIC and
file_.status == amo.STATUS_UNREVIEWED):
# Add-on or file is waiting for a full review.
return 'full' return 'full'
if addon_status == amo.STATUS_UNREVIEWED:
# Add-on is waiting for a prelim review.
return 'prelim'
if file_.status == amo.STATUS_UNREVIEWED:
# Addon is reviewed, not file.
if addon_status == amo.STATUS_PUBLIC:
return 'full'
elif addon_status == amo.STATUS_LITE:
return 'prelim'

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

@ -121,11 +121,8 @@ def id_function(fixture_value):
@pytest.fixture( @pytest.fixture(
params=[(amo.STATUS_UNREVIEWED, amo.STATUS_UNREVIEWED, 'prelim'), params=[(amo.STATUS_NOMINATED, amo.STATUS_UNREVIEWED, 'full'),
(amo.STATUS_LITE, amo.STATUS_UNREVIEWED, 'prelim'), (amo.STATUS_PUBLIC, amo.STATUS_UNREVIEWED, 'full')],
(amo.STATUS_NOMINATED, amo.STATUS_UNREVIEWED, 'full'),
(amo.STATUS_PUBLIC, amo.STATUS_UNREVIEWED, 'full'),
(amo.STATUS_LITE_AND_NOMINATED, amo.STATUS_LITE, 'full')],
# ids are used to build better names for the tests using this fixture. # ids are used to build better names for the tests using this fixture.
ids=id_function) ids=id_function)
def use_case(request, db): def use_case(request, db):
@ -133,11 +130,8 @@ def use_case(request, db):
Addon | File1 and 2 | Review type Addon | File1 and 2 | Review type
============================================================== ==============================================================
waiting for prelim | unreviewed | prelim reviewed
prelim reviewed | unreviewed | prelim reviewed
waiting for full | unreviewed | fully reviewed waiting for full | unreviewed | fully reviewed
fully reviewed | unreviewed | fully reviewed fully reviewed | unreviewed | fully reviewed
prelim waiting for full | prelim reviewed | fully reviewed
""" """
addon_status, file_status, review_type = request.param addon_status, file_status, review_type = request.param
@ -194,10 +188,8 @@ def test_approve_addons_approve_files(use_case, mozilla_user):
addon, file1, file2, review_type = use_case addon, file1, file2, review_type = use_case
approve_addons.approve_files([(file1, review_type), approve_addons.approve_files([(file1, review_type),
(file2, review_type)]) (file2, review_type)])
assert file1.reload().status == ( assert file1.reload().status == amo.STATUS_PUBLIC
amo.STATUS_LITE if review_type == 'prelim' else amo.STATUS_PUBLIC) assert file2.reload().status == amo.STATUS_PUBLIC
assert file2.reload().status == (
amo.STATUS_LITE if review_type == 'prelim' else amo.STATUS_PUBLIC)
logs = AddonLog.objects.filter(addon=addon) logs = AddonLog.objects.filter(addon=addon)
assert len(logs) == 2 # One per file. assert len(logs) == 2 # One per file.
file1_log, file2_log = logs file1_log, file2_log = logs

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

@ -373,7 +373,7 @@ class ReviewForm(happyforms.Form):
responses = CannedResponse.objects.filter(type=self.type) responses = CannedResponse.objects.filter(type=self.type)
# Loop through the actions (prelim, public, etc). # Loop through the actions (public, etc).
for k, action in self.helper.actions.iteritems(): for k, action in self.helper.actions.iteritems():
action_choices = [[c.response, c.name] for c in responses action_choices = [[c.response, c.name] for c in responses
if c.sort_group and k in c.sort_group.split(',')] if c.sort_group and k in c.sort_group.split(',')]

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

@ -26,8 +26,8 @@ from olympia.amo.utils import send_mail as amo_send_mail, to_language
from olympia.constants.base import REVIEW_LIMITED_DELAY_HOURS from olympia.constants.base import REVIEW_LIMITED_DELAY_HOURS
from olympia.editors.models import ( from olympia.editors.models import (
ReviewerScore, ViewFullReviewQueue, ViewPendingQueue, ReviewerScore, ViewFullReviewQueue, ViewPendingQueue,
ViewPreliminaryQueue, ViewUnlistedAllList, ViewUnlistedFullReviewQueue, ViewUnlistedAllList, ViewUnlistedFullReviewQueue,
ViewUnlistedPendingQueue, ViewUnlistedPreliminaryQueue) ViewUnlistedPendingQueue)
from olympia.lib.crypto.packaged import sign_file from olympia.lib.crypto.packaged import sign_file
from olympia.users.models import UserProfile from olympia.users.models import UserProfile
@ -48,19 +48,7 @@ def file_compare(file_obj, version):
@register.function @register.function
def file_review_status(addon, file): def file_review_status(addon, file):
# If the file is pending review, check the add-on status if file.status == amo.STATUS_DISABLED:
if file.status == amo.STATUS_UNREVIEWED:
if addon.status in [amo.STATUS_NOMINATED, amo.STATUS_PUBLIC]:
return _(u'Pending Full Review')
if addon.status in [amo.STATUS_UNREVIEWED, amo.STATUS_LITE]:
return _(u'Pending Preliminary Review')
# Special case: prelim upgrading to full approval,
# file can already be preliminary reviewed or not
if (file.status in [amo.STATUS_LITE, amo.STATUS_UNREVIEWED] and
addon.status == amo.STATUS_LITE_AND_NOMINATED):
if addon.latest_version.version_int == file.version.version_int:
return _(u'Pending Full Review')
if file.status in [amo.STATUS_DISABLED, amo.STATUS_REJECTED]:
if file.reviewed is not None: if file.reviewed is not None:
return _(u'Rejected') return _(u'Rejected')
# Can't assume that if the reviewed date is missing its # Can't assume that if the reviewed date is missing its
@ -111,12 +99,8 @@ def editors_breadcrumbs(context, queue=None, addon_queue=None, items=None,
if addon_queue: if addon_queue:
queue_id = addon_queue.status queue_id = addon_queue.status
queue_ids = {amo.STATUS_UNREVIEWED: 'prelim', queue_ids = {amo.STATUS_NOMINATED: 'nominated',
amo.STATUS_NOMINATED: 'nominated', amo.STATUS_PUBLIC: 'pending'}
amo.STATUS_PUBLIC: 'pending',
amo.STATUS_LITE: 'prelim',
amo.STATUS_LITE_AND_NOMINATED: 'nominated',
amo.STATUS_PENDING: 'pending'}
queue = queue_ids.get(queue_id, 'queue') queue = queue_ids.get(queue_id, 'queue')
@ -128,7 +112,6 @@ def editors_breadcrumbs(context, queue=None, addon_queue=None, items=None,
'queue': _('Queue'), 'queue': _('Queue'),
'pending': _('Pending Updates'), 'pending': _('Pending Updates'),
'nominated': _('Full Reviews'), 'nominated': _('Full Reviews'),
'prelim': _('Preliminary Reviews'),
'moderated': _('Moderated Reviews'), 'moderated': _('Moderated Reviews'),
'pending_themes': _('Pending Themes'), 'pending_themes': _('Pending Themes'),
@ -140,7 +123,6 @@ def editors_breadcrumbs(context, queue=None, addon_queue=None, items=None,
'queue': _('Queue'), 'queue': _('Queue'),
'pending': _('Unlisted Pending Updates'), 'pending': _('Unlisted Pending Updates'),
'nominated': _('Unlisted Full Reviews'), 'nominated': _('Unlisted Full Reviews'),
'prelim': _('Unlisted Preliminary Reviews'),
'all': _('All Unlisted Add-ons'), 'all': _('All Unlisted Add-ons'),
} }
@ -181,11 +163,6 @@ def queue_tabnav(context):
'Pending Updates ({0})', 'Pending Updates ({0})',
counts['pending']) counts['pending'])
.format(counts['pending']))), .format(counts['pending']))),
('prelim', 'queue_prelim',
(ngettext('Preliminary Review ({0})',
'Preliminary Reviews ({0})',
counts['prelim'])
.format(counts['prelim']))),
('moderated', 'queue_moderated', ('moderated', 'queue_moderated',
(ngettext('Moderated Review ({0})', (ngettext('Moderated Review ({0})',
'Moderated Reviews ({0})', 'Moderated Reviews ({0})',
@ -202,11 +179,6 @@ def queue_tabnav(context):
'Unlisted Pending Updates ({0})', 'Unlisted Pending Updates ({0})',
unlisted_counts['pending']) unlisted_counts['pending'])
.format(unlisted_counts['pending']))), .format(unlisted_counts['pending']))),
('prelim', 'unlisted_queue_prelim',
(ngettext('Unlisted Preliminary Review ({0})',
'Unlisted Preliminary Reviews ({0})',
unlisted_counts['prelim'])
.format(unlisted_counts['prelim']))),
('all', 'unlisted_queue_all', ('all', 'unlisted_queue_all',
(ngettext('All Unlisted Add-ons ({0})', (ngettext('All Unlisted Add-ons ({0})',
'All Unlisted Add-ons ({0})', 'All Unlisted Add-ons ({0})',
@ -419,12 +391,6 @@ class ViewFullReviewQueueTable(EditorQueueTable):
model = ViewFullReviewQueue model = ViewFullReviewQueue
class ViewPreliminaryQueueTable(EditorQueueTable):
class Meta(EditorQueueTable.Meta):
model = ViewPreliminaryQueue
class ViewUnlistedPendingQueueTable(EditorQueueTable): class ViewUnlistedPendingQueueTable(EditorQueueTable):
class Meta(EditorQueueTable.Meta): class Meta(EditorQueueTable.Meta):
@ -437,12 +403,6 @@ class ViewUnlistedFullReviewQueueTable(EditorQueueTable):
model = ViewUnlistedFullReviewQueue model = ViewUnlistedFullReviewQueue
class ViewUnlistedPreliminaryQueueTable(EditorQueueTable):
class Meta(EditorQueueTable.Meta):
model = ViewUnlistedPreliminaryQueue
class ViewUnlistedAllListTable(EditorAllListTable): class ViewUnlistedAllListTable(EditorAllListTable):
class Meta(EditorQueueTable.Meta): class Meta(EditorQueueTable.Meta):
@ -452,8 +412,6 @@ class ViewUnlistedAllListTable(EditorAllListTable):
log = commonware.log.getLogger('z.mailer') log = commonware.log.getLogger('z.mailer')
NOMINATED_STATUSES = (amo.STATUS_NOMINATED, amo.STATUS_LITE_AND_NOMINATED)
PRELIMINARY_STATUSES = (amo.STATUS_UNREVIEWED, amo.STATUS_LITE)
PENDING_STATUSES = (amo.STATUS_BETA, amo.STATUS_DISABLED, amo.STATUS_NULL, PENDING_STATUSES = (amo.STATUS_BETA, amo.STATUS_DISABLED, amo.STATUS_NULL,
amo.STATUS_PENDING, amo.STATUS_PUBLIC) amo.STATUS_PENDING, amo.STATUS_PUBLIC)
@ -510,17 +468,9 @@ class ReviewHelper:
self.handler.set_data(data) self.handler.set_data(data)
def get_review_type(self, request, addon, version): def get_review_type(self, request, addon, version):
if self.addon.status in NOMINATED_STATUSES: if self.addon.status == amo.STATUS_NOMINATED:
self.review_type = 'nominated' self.review_type = 'nominated'
self.handler = ReviewAddon(request, addon, version, 'nominated') self.handler = ReviewAddon(request, addon, version, 'nominated')
elif self.addon.status == amo.STATUS_UNREVIEWED:
self.review_type = 'preliminary'
self.handler = ReviewAddon(request, addon, version, 'preliminary')
elif self.addon.status == amo.STATUS_LITE:
self.review_type = 'preliminary'
self.handler = ReviewFiles(request, addon, version, 'preliminary')
else: else:
self.review_type = 'pending' self.review_type = 'pending'
self.handler = ReviewFiles(request, addon, version, 'pending') self.handler = ReviewFiles(request, addon, version, 'pending')
@ -532,7 +482,6 @@ class ReviewHelper:
# ReviewHelper for its `handler` attribute and we don't care about # ReviewHelper for its `handler` attribute and we don't care about
# the actions. # the actions.
return actions return actions
labels, details = self._review_actions()
reviewable_because_complete = addon.status not in ( reviewable_because_complete = addon.status not in (
amo.STATUS_NULL, amo.STATUS_DELETED) amo.STATUS_NULL, amo.STATUS_DELETED)
reviewable_because_admin = ( reviewable_because_admin = (
@ -544,101 +493,51 @@ class ReviewHelper:
addon.latest_version.nomination is not None and addon.latest_version.nomination is not None and
(datetime.datetime.now() - addon.latest_version.nomination >= (datetime.datetime.now() - addon.latest_version.nomination >=
datetime.timedelta(hours=REVIEW_LIMITED_DELAY_HOURS)))) datetime.timedelta(hours=REVIEW_LIMITED_DELAY_HOURS))))
reviewable_because_pending = addon.latest_version is not None and ( reviewable_because_pending = (
len(addon.latest_version.is_unreviewed) > 0 or addon.latest_version is not None and
addon.status == amo.STATUS_LITE_AND_NOMINATED) len(addon.latest_version.is_unreviewed) > 0)
if (reviewable_because_complete and if (reviewable_because_complete and
reviewable_because_admin and reviewable_because_admin and
reviewable_because_submission_time and reviewable_because_submission_time and
reviewable_because_pending): reviewable_because_pending):
if self.review_type != 'preliminary': actions['public'] = {
if addon.is_listed: 'method': self.handler.process_public,
label = _lazy('Push to public') 'minimal': False,
else: 'details': _lazy('This will approve, sign, and publish this '
label = _lazy('Grant full review') 'version. The comments will be sent to the '
actions['public'] = {'method': self.handler.process_public, 'developer.'),
'minimal': False, 'label': _lazy('Approve')}
'label': label} actions['reject'] = {
# An unlisted sideload add-on, which requests a full review, cannot 'method': self.handler.process_sandbox,
# be granted a preliminary review. 'label': _lazy('Reject'),
prelim_allowed = not waffle.flag_is_active( 'details': _lazy('This will reject this version and remove it '
request, 'no-prelim-review') and addon.is_listed 'from the queue. The comments will be sent '
if prelim_allowed or self.review_type == 'preliminary': 'to the developer.'),
actions['prelim'] = { 'minimal': False}
'method': self.handler.process_preliminary, actions['info'] = {
'label': labels['prelim'], 'method': self.handler.request_information,
'minimal': False} 'label': _lazy('Request more information'),
actions['reject'] = {'method': self.handler.process_sandbox, 'details': _lazy('This will request more information from the '
'label': _lazy('Reject'), 'developer. You will be notified when they '
'minimal': False} 'reply.'),
actions['info'] = {'method': self.handler.request_information, 'minimal': True}
'label': _lazy('Request more information'), actions['super'] = {
'minimal': True} 'method': self.handler.process_super_review,
actions['super'] = {'method': self.handler.process_super_review, 'label': _lazy('Request super-review'),
'label': _lazy('Request super-review'), 'details': _lazy('If you have concerns about this add-on that an '
'minimal': True} 'admin reviewer should look into, enter your '
actions['comment'] = {'method': self.handler.process_comment, 'comments in the area below. They will not be '
'label': _lazy('Comment'), 'sent to the developer.'),
'minimal': True} 'minimal': True}
for k, v in actions.items(): actions['comment'] = {
v['details'] = details.get(k) 'method': self.handler.process_comment,
'label': _lazy('Comment'),
'details': _lazy('Make a comment on this version. The developer '
'won\'t be able to see this.'),
'minimal': True}
return actions return actions
def _review_actions(self):
labels = {'prelim': _lazy('Grant preliminary review')}
details = {'prelim': _lazy('This will mark the files as '
'preliminarily reviewed.'),
'info': _lazy('Use this form to request more information '
'from the author. They will receive an email '
'and be able to answer here. You will be '
'notified by email when they reply.'),
'super': _lazy('If you have concerns about this add-on\'s '
'security, copyright issues, or other '
'concerns that an administrator should look '
'into, enter your comments in the area '
'below. They will be sent to '
'administrators, not the author.'),
'reject': _lazy('This will reject the add-on and remove '
'it from the review queue.'),
'comment': _lazy('Make a comment on this version. The '
'author won\'t be able to see this.')}
if self.addon.status == amo.STATUS_LITE:
details['reject'] = _lazy('This will reject the files and remove '
'them from the review queue.')
if self.addon.status in (amo.STATUS_UNREVIEWED, amo.STATUS_NOMINATED):
details['prelim'] = _lazy('This will mark the add-on as '
'preliminarily reviewed. Future '
'versions will undergo '
'preliminary review.')
elif self.addon.status == amo.STATUS_LITE:
details['prelim'] = _lazy('This will mark the files as '
'preliminarily reviewed. Future '
'versions will undergo '
'preliminary review.')
elif self.addon.status == amo.STATUS_LITE_AND_NOMINATED:
labels['prelim'] = _lazy('Retain preliminary review')
details['prelim'] = _lazy('This will retain the add-on as '
'preliminarily reviewed. Future '
'versions will undergo preliminary '
'review.')
if self.review_type == 'pending':
details['public'] = _lazy('This will approve a sandboxed version '
'of a public add-on to appear on the '
'public site.')
details['reject'] = _lazy('This will reject a version of a public '
'add-on and remove it from the queue.')
else:
details['public'] = _lazy('This will mark the add-on and its most '
'recent version and files as public. '
'Future versions will go into the '
'sandbox until they are reviewed by an '
'editor.')
return labels, details
def process(self): def process(self):
action = self.handler.data.get('action', '') action = self.handler.data.get('action', '')
if not action: if not action:
@ -785,21 +684,11 @@ class ReviewBase(object):
class ReviewAddon(ReviewBase): class ReviewAddon(ReviewBase):
def __init__(self, *args, **kwargs):
super(ReviewAddon, self).__init__(*args, **kwargs)
self.is_upgrade = (
self.addon.status == amo.STATUS_LITE_AND_NOMINATED and
self.review_type == 'nominated')
def set_data(self, data): def set_data(self, data):
self.data = data self.data = data
def process_public(self, auto_validation=False): def process_public(self, auto_validation=False):
"""Set an addon to public.""" """Set an addon to public."""
if self.review_type == 'preliminary':
raise AssertionError('Preliminary addons cannot be made public.')
# Sign addon. # Sign addon.
for file_ in self.files: for file_ in self.files:
sign_file(file_, settings.SIGNING_SERVER) sign_file(file_, settings.SIGNING_SERVER)
@ -835,13 +724,7 @@ class ReviewAddon(ReviewBase):
# Hold onto the status before we change it. # Hold onto the status before we change it.
status = self.addon.status status = self.addon.status
if (not self.is_upgrade or self.set_addon(status=amo.STATUS_NULL)
not self.addon.versions.exclude(id=self.version.id)
.filter(files__status__in=amo.REVIEWED_STATUSES)):
self.set_addon(status=amo.STATUS_NULL)
else:
self.set_addon(status=amo.STATUS_LITE)
self.set_files(amo.STATUS_DISABLED, self.files, self.set_files(amo.STATUS_DISABLED, self.files,
hide_disabled_file=True) hide_disabled_file=True)
@ -860,40 +743,6 @@ class ReviewAddon(ReviewBase):
if self.request: if self.request:
ReviewerScore.award_points(self.request.user, self.addon, status) ReviewerScore.award_points(self.request.user, self.addon, status)
def process_preliminary(self, auto_validation=False):
"""Set an addon to preliminary."""
# Sign addon.
for file_ in self.files:
sign_file(file_, settings.PRELIMINARY_SIGNING_SERVER)
# Hold onto the status before we change it.
status = self.addon.status
changes = {'status': amo.STATUS_LITE}
template = u'%s_to_preliminary' % self.review_type
subject = u'Mozilla Add-ons: %s %s Preliminary Reviewed'
if (self.review_type == 'preliminary' and
self.addon.status == amo.STATUS_LITE_AND_NOMINATED):
template = u'nominated_to_nominated'
if not self.addon.is_listed:
template = u'unlisted_to_reviewed'
if auto_validation:
template = u'unlisted_to_reviewed_auto'
subject = u'Mozilla Add-ons: %s %s signed and ready to download'
self.set_addon(**changes)
self.set_files(amo.STATUS_LITE, self.files, copy_to_mirror=True)
self.log_action(amo.LOG.PRELIMINARY_VERSION)
self.notify_email(template, subject)
log.info(u'Making %s preliminary' % (self.addon))
log.info(u'Sending email for %s' % (self.addon))
if self.request and not auto_validation:
# Assign reviewer incentive scores.
ReviewerScore.award_points(self.request.user, self.addon, status)
def process_super_review(self): def process_super_review(self):
"""Give an addon super review.""" """Give an addon super review."""
self.addon.update(admin_review=True) self.addon.update(admin_review=True)
@ -911,9 +760,6 @@ class ReviewFiles(ReviewBase):
def process_public(self, auto_validation=False): def process_public(self, auto_validation=False):
"""Set an addons files to public.""" """Set an addons files to public."""
if self.review_type == 'preliminary':
raise AssertionError('Preliminary addons cannot be made public.')
# Sign addon. # Sign addon.
for file_ in self.files: for file_ in self.files:
sign_file(file_, settings.SIGNING_SERVER) sign_file(file_, settings.SIGNING_SERVER)
@ -966,37 +812,8 @@ class ReviewFiles(ReviewBase):
if self.request: if self.request:
ReviewerScore.award_points(self.request.user, self.addon, status) ReviewerScore.award_points(self.request.user, self.addon, status)
def process_preliminary(self, auto_validation=False):
"""Set an addons files to preliminary."""
# Sign addon.
for file_ in self.files:
sign_file(file_, settings.PRELIMINARY_SIGNING_SERVER)
# Hold onto the status before we change it.
status = self.addon.status
self.set_files(amo.STATUS_LITE, self.files, copy_to_mirror=True)
self.log_action(amo.LOG.PRELIMINARY_VERSION)
template = u'%s_to_preliminary' % self.review_type
subject = u'Mozilla Add-ons: %s %s Preliminary Reviewed'
if not self.addon.is_listed:
template = u'unlisted_to_reviewed'
if auto_validation:
template = u'unlisted_to_reviewed_auto'
subject = u'Mozilla Add-ons: %s %s signed and ready to download'
self.notify_email(template, subject)
log.info(u'Making %s files %s preliminary' %
(self.addon, ', '.join([f.filename for f in self.files])))
log.info(u'Sending email for %s' % (self.addon))
if self.request and not auto_validation:
# Assign reviewer incentive scores.
ReviewerScore.award_points(self.request.user, self.addon, status)
def process_super_review(self): def process_super_review(self):
"""Give an addon super review when preliminary.""" """Give an addon super review."""
self.addon.update(admin_review=True) self.addon.update(admin_review=True)
self.notify_email('author_super_review', self.notify_email('author_super_review',

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

@ -201,9 +201,7 @@ class ViewFullReviewQueue(ViewQueue):
def base_query(self): def base_query(self):
q = super(ViewFullReviewQueue, self).base_query() q = super(ViewFullReviewQueue, self).base_query()
q['where'].extend(['files.status <> %s' % amo.STATUS_BETA, q['where'].extend(['files.status <> %s' % amo.STATUS_BETA,
'addons.status IN (%s, %s)' % ( 'addons.status = %s' % amo.STATUS_NOMINATED])
amo.STATUS_NOMINATED,
amo.STATUS_LITE_AND_NOMINATED)])
return q return q
@ -216,17 +214,6 @@ class ViewPendingQueue(ViewQueue):
return q return q
class ViewPreliminaryQueue(ViewQueue):
def base_query(self):
q = super(ViewPreliminaryQueue, self).base_query()
q['where'].extend(['files.status = %s' % amo.STATUS_UNREVIEWED,
'addons.status IN (%s, %s)' % (
amo.STATUS_LITE,
amo.STATUS_UNREVIEWED)])
return q
class ViewAllList(RawSQLModel): class ViewAllList(RawSQLModel):
id = models.IntegerField() id = models.IntegerField()
addon_name = models.CharField(max_length=255) addon_name = models.CharField(max_length=255)
@ -316,10 +303,6 @@ class ViewUnlistedPendingQueue(ViewPendingQueue):
listed = False listed = False
class ViewUnlistedPreliminaryQueue(ViewPreliminaryQueue):
listed = False
class ViewUnlistedAllList(ViewAllList): class ViewUnlistedAllList(ViewAllList):
listed = False listed = False
@ -434,9 +417,7 @@ class ReviewerScore(ModelBase):
""" """
queue = '' queue = ''
if status in [amo.STATUS_UNREVIEWED, amo.STATUS_LITE]: if status == amo.STATUS_NOMINATED:
queue = 'PRELIM'
elif status in [amo.STATUS_NOMINATED, amo.STATUS_LITE_AND_NOMINATED]:
queue = 'FULL' queue = 'FULL'
elif status == amo.STATUS_PUBLIC: elif status == amo.STATUS_PUBLIC:
queue = 'UPDATE' queue = 'UPDATE'

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

@ -48,8 +48,6 @@
{{ _('Full Reviews') }} ({{ queue_counts['nominated'] }})</a></li> {{ _('Full Reviews') }} ({{ queue_counts['nominated'] }})</a></li>
<li><a href="{{ url('editors.queue_pending') }}"> <li><a href="{{ url('editors.queue_pending') }}">
{{ _('Pending Updates') }} ({{ queue_counts['pending'] }})</a></li> {{ _('Pending Updates') }} ({{ queue_counts['pending'] }})</a></li>
<li><a href="{{ url('editors.queue_prelim') }}">
{{ _('Preliminary Reviews') }} ({{ queue_counts['prelim'] }})</a></li>
<li><a href="{{ url('editors.queue_moderated') }}"> <li><a href="{{ url('editors.queue_moderated') }}">
{{ _('Moderated Reviews') }} ({{ queue_counts['moderated'] }})</a></li> {{ _('Moderated Reviews') }} ({{ queue_counts['moderated'] }})</a></li>
</ul> </ul>
@ -63,8 +61,6 @@
{{ _('Full Reviews') }} ({{ unlisted_queue_counts['nominated'] }})</a></li> {{ _('Full Reviews') }} ({{ unlisted_queue_counts['nominated'] }})</a></li>
<li><a href="{{ url('editors.unlisted_queue_pending') }}"> <li><a href="{{ url('editors.unlisted_queue_pending') }}">
{{ _('Pending Updates') }} ({{ unlisted_queue_counts['pending'] }})</a></li> {{ _('Pending Updates') }} ({{ unlisted_queue_counts['pending'] }})</a></li>
<li><a href="{{ url('editors.unlisted_queue_prelim') }}">
{{ _('Preliminary Reviews') }} ({{ unlisted_queue_counts['prelim'] }})</a></li>
<li><a href="{{ url('editors.unlisted_queue_all') }}"> <li><a href="{{ url('editors.unlisted_queue_all') }}">
{{ _('All Add-ons') }} ({{ unlisted_queue_counts['all'] }})</a></li> {{ _('All Add-ons') }} ({{ unlisted_queue_counts['all'] }})</a></li>
</ul> </ul>

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

@ -1,14 +0,0 @@
{% extends "editors/emails/base.ltxt" %}{% block content %}
Your add-on, {{ name }} {{ number }}, has been reviewed and did not meet the criteria for full review. However, it has been granted preliminary review and is now available for download in our gallery at {{ addon_url }}
{% include "editors/emails/files.ltxt" %}
Reviewer:
{{ reviewer }}
Comments:
{{ comments }}
{{ tested }}
Your add-on will now appear in search results and categories with some limitations. You may re-request full review by addressing the reviewer's comments and uploading a new version.
{% endblock %}

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

@ -1,12 +0,0 @@
{% extends "editors/emails/base.ltxt" %}{% block content %}
Your add-on, {{ name }} {{ number }}, has been preliminarily reviewed and is now available for download in our gallery at {{ addon_url }}
{% include "editors/emails/files.ltxt" %}
Reviewer:
{{ reviewer }}
Comments:
{{ comments }}
{{ tested }}
{% endblock %}

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

@ -1,13 +0,0 @@
{% extends "editors/emails/base.ltxt" %}{% block content %}
Your add-on, {{ name }}, {{ number }}, has been preliminarily reviewed and is now available for download in our gallery at {{ addon_url }}
{% include "editors/emails/files.ltxt" %}
Reviewer:
{{ reviewer }}
Comments:
{{ comments }}
{{ tested }}
Your add-on will now appear in search results and categories with some limitations. You may request full review to remove these limitations.
{% endblock %}

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

@ -1,13 +0,0 @@
{% extends "editors/emails/base.ltxt" %}{% block content %}
Your add-on, {{ name }} {{ number }}, has been reviewed and did not meet the criteria for being hosted in our gallery.
Reviewer:
{{ reviewer }}
Comments:
{{ comments }}
{{ tested }}
This version of your add-on has been disabled. You may re-request review by addressing the reviewer's comments and uploading a new version at {{ dev_versions_url }}
{% endblock %}

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

@ -20,17 +20,10 @@
queue_counts_total['pending'])|f(num=queue_counts_total['pending']) }} queue_counts_total['pending'])|f(num=queue_counts_total['pending']) }}
</a> </a>
</div> </div>
<div class="editor-stats-title">
<a href="{{ url('editors.queue_prelim') }}">
{{ ngettext('Preliminary Review ({num})',
'Preliminary Reviews ({num})',
queue_counts_total['prelim'])|f(num=queue_counts_total['prelim']) }}
</a>
</div>
</div> </div>
<div class="editor-stats"> <div class="editor-stats">
{% for type in ('nominated', 'pending', 'prelim'): %} {% for type in ('nominated', 'pending'): %}
<div class="editor-stats-table"> <div class="editor-stats-table">
<div class="editor-stats-dark"> <div class="editor-stats-dark">
<strong>{{ _('Current waiting times:') }}</strong> <strong>{{ _('Current waiting times:') }}</strong>
@ -70,17 +63,10 @@
unlisted_queue_counts['pending'])|f(num=unlisted_queue_counts['pending']) }} unlisted_queue_counts['pending'])|f(num=unlisted_queue_counts['pending']) }}
</a> </a>
</div> </div>
<div class="editor-stats-title">
<a href="{{ url('editors.unlisted_queue_prelim') }}">
{{ ngettext('Unlisted Preliminary Review ({num})',
'Unlisted Preliminary Reviews ({num})',
unlisted_queue_counts['prelim'])|f(num=unlisted_queue_counts['prelim']) }}
</a>
</div>
</div> </div>
<div class="editor-stats"> <div class="editor-stats">
{% for type in ('nominated', 'pending', 'prelim'): %} {% for type in ('nominated', 'pending'): %}
<div class="editor-stats-table"> <div class="editor-stats-table">
<div class="editor-stats-dark"> <div class="editor-stats-dark">
<strong>{{ _('Current waiting times:') }}</strong> <strong>{{ _('Current waiting times:') }}</strong>
@ -106,12 +92,12 @@
<div class="featured" id="editors-stats"> <div class="featured" id="editors-stats">
<div class="featured-inner"> <div class="featured-inner">
<div class="listing-header"> <div class="listing-header">
<div class="editor-stats-title"><span>{{ _('Total Reviews') }}</span></div> <div class="editor-stats-title three-col"><span>{{ _('Total Reviews') }}</span></div>
<div class="editor-stats-title"><span>{{ _('Reviews This Month') }}</span></div> <div class="editor-stats-title three-col"><span>{{ _('Reviews This Month') }}</span></div>
<div class="editor-stats-title"><span>{{ _('New Editors') }}</span></div> <div class="editor-stats-title three-col"><span>{{ _('New Editors') }}</span></div>
</div> </div>
<div class="editor-stats"> <div class="editor-stats">
<div class="editor-stats-table"> <div class="editor-stats-table three-col">
<div> <div>
<table> <table>
{% for row in reviews_total: %} {% for row in reviews_total: %}
@ -126,7 +112,7 @@
<div>{{ _("You're #{0} with {1} reviews")|f(reviews_total_position, reviews_total_count) }}</div> <div>{{ _("You're #{0} with {1} reviews")|f(reviews_total_position, reviews_total_count) }}</div>
{% endif %} {% endif %}
</div> </div>
<div class="editor-stats-table"> <div class="editor-stats-table three-col">
<div> <div>
<table> <table>
{% for row in reviews_monthly: %} {% for row in reviews_monthly: %}
@ -141,7 +127,7 @@
<div>{{ _("You're #{0} with {1} reviews")|f(reviews_monthly_position, reviews_monthly_count) }}</div> <div>{{ _("You're #{0} with {1} reviews")|f(reviews_monthly_position, reviews_monthly_count) }}</div>
{% endif %} {% endif %}
</div> </div>
<div class="editor-stats-table"> <div class="editor-stats-table three-col">
<div> <div>
<table> <table>
{% for editors in new_editors %} {% for editors in new_editors %}

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

@ -2,13 +2,11 @@ import mock
from django.utils.encoding import force_text from django.utils.encoding import force_text
from waffle.testutils import override_flag
from olympia import amo from olympia import amo
from olympia.amo.tests import TestCase from olympia.amo.tests import TestCase
from olympia.addons.models import Addon from olympia.addons.models import Addon
from olympia.editors.forms import ReviewForm from olympia.editors.forms import ReviewForm
from olympia.editors.helpers import NOMINATED_STATUSES, ReviewHelper from olympia.editors.helpers import ReviewHelper
from olympia.editors.models import CannedResponse from olympia.editors.models import CannedResponse
from olympia.users.models import UserProfile from olympia.users.models import UserProfile
@ -36,48 +34,17 @@ class TestReviewActions(TestCase):
version=self.version)) version=self.version))
return form.helper.get_actions(self.request, self.addon) return form.helper.get_actions(self.request, self.addon)
def test_lite_nominated(self): def test_nominated_addon(self):
status = self.set_statuses(addon_status=amo.STATUS_LITE_AND_NOMINATED,
file_status=amo.STATUS_UNREVIEWED)
assert force_text(status['prelim']['label']) == (
'Retain preliminary review')
def test_other_statuses(self):
for status in Addon.STATUS_CHOICES:
statuses = NOMINATED_STATUSES + (
amo.STATUS_NULL, amo.STATUS_DELETED)
if status in statuses:
return
else:
label = self.set_statuses(
addon_status=status,
file_status=amo.STATUS_UNREVIEWED)['prelim']['label']
assert force_text(label) == 'Grant preliminary review'
def test_nominated_unlisted_addon_no_prelim(self):
self.addon.update(is_listed=False) self.addon.update(is_listed=False)
actions = self.set_statuses(addon_status=amo.STATUS_NOMINATED, actions = self.set_statuses(addon_status=amo.STATUS_NOMINATED,
file_status=amo.STATUS_UNREVIEWED) file_status=amo.STATUS_UNREVIEWED)
assert 'prelim' not in actions assert actions['public']['label'] == 'Approve'
assert actions['public']['label'] == 'Grant full review'
def test_reject(self): def test_reject(self):
reject = self.set_statuses( reject = self.set_statuses(
addon_status=amo.STATUS_UNREVIEWED, addon_status=amo.STATUS_NOMINATED,
file_status=amo.STATUS_UNREVIEWED)['reject']['details'] file_status=amo.STATUS_UNREVIEWED)['reject']['details']
assert force_text(reject).startswith('This will reject the add-on') assert force_text(reject).startswith('This will reject this version')
def test_reject_lite(self):
reject = self.set_statuses(
addon_status=amo.STATUS_LITE,
file_status=amo.STATUS_UNREVIEWED)['reject']['details']
assert force_text(reject).startswith('This will reject the files')
def test_not_public(self):
# If the file is pending preliminary review then there is no option to
# grant full review so the length of the actions is one shorter
assert len(self.set_statuses(addon_status=amo.STATUS_UNREVIEWED,
file_status=amo.STATUS_UNREVIEWED)) == 5
def test_addon_status_null(self): def test_addon_status_null(self):
# If the add-on is null we only show info, comment and super review. # If the add-on is null we only show info, comment and super review.
@ -96,8 +63,6 @@ class TestReviewActions(TestCase):
file_status=amo.STATUS_PUBLIC)) == 3 file_status=amo.STATUS_PUBLIC)) == 3
assert len(self.set_statuses(addon_status=amo.STATUS_PUBLIC, assert len(self.set_statuses(addon_status=amo.STATUS_PUBLIC,
file_status=amo.STATUS_BETA)) == 3 file_status=amo.STATUS_BETA)) == 3
assert len(self.set_statuses(addon_status=amo.STATUS_LITE,
file_status=amo.STATUS_LITE)) == 3
assert len(self.set_statuses(addon_status=amo.STATUS_DISABLED, assert len(self.set_statuses(addon_status=amo.STATUS_DISABLED,
file_status=amo.STATUS_DISABLED)) == 3 file_status=amo.STATUS_DISABLED)) == 3
@ -106,43 +71,12 @@ class TestReviewActions(TestCase):
self.addon.update(admin_review=True) self.addon.update(admin_review=True)
# Test with an admin editor. # Test with an admin editor.
action_allowed_mock.return_value = True action_allowed_mock.return_value = True
status = self.set_statuses(addon_status=amo.STATUS_LITE_AND_NOMINATED, status = self.set_statuses(addon_status=amo.STATUS_NOMINATED,
file_status=amo.STATUS_UNREVIEWED)
assert 'public' in status.keys()
assert 'prelim' in status.keys()
# Test with an non-admin editor.
action_allowed_mock.return_value = False
status = self.set_statuses(addon_status=amo.STATUS_LITE_AND_NOMINATED,
file_status=amo.STATUS_UNREVIEWED)
assert 'public' not in status.keys()
assert 'prelim' not in status.keys()
@override_flag('no-prelim-review', active=True)
class TestReviewActionsNoPrelim(TestReviewActions):
def test_lite_nominated(self):
""" Without prelim this shouldn't be an option."""
status = self.set_statuses(addon_status=amo.STATUS_LITE_AND_NOMINATED,
file_status=amo.STATUS_UNREVIEWED)
assert 'prelim' not in status
def test_nominated_addon_no_prelim(self):
actions = self.set_statuses(addon_status=amo.STATUS_NOMINATED,
file_status=amo.STATUS_UNREVIEWED)
assert 'prelim' not in actions
@mock.patch('olympia.access.acl.action_allowed')
def test_admin_flagged_addon_actions(self, action_allowed_mock):
self.addon.update(admin_review=True)
# Test with an admin editor.
action_allowed_mock.return_value = True
status = self.set_statuses(addon_status=amo.STATUS_LITE_AND_NOMINATED,
file_status=amo.STATUS_UNREVIEWED) file_status=amo.STATUS_UNREVIEWED)
assert 'public' in status.keys() assert 'public' in status.keys()
# Test with an non-admin editor. # Test with an non-admin editor.
action_allowed_mock.return_value = False action_allowed_mock.return_value = False
status = self.set_statuses(addon_status=amo.STATUS_LITE_AND_NOMINATED, status = self.set_statuses(addon_status=amo.STATUS_NOMINATED,
file_status=amo.STATUS_UNREVIEWED) file_status=amo.STATUS_UNREVIEWED)
assert 'public' not in status.keys() assert 'public' not in status.keys()

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

@ -9,7 +9,7 @@ from django.utils import translation
import pytest import pytest
from mock import Mock, patch from mock import Mock, patch
from pyquery import PyQuery as pq from pyquery import PyQuery as pq
from waffle.testutils import override_flag, override_switch from waffle.testutils import override_switch
from olympia import amo from olympia import amo
from olympia.activity.models import ActivityLogToken from olympia.activity.models import ActivityLogToken
@ -24,16 +24,11 @@ from olympia.translations.models import Translation
from olympia.users.models import UserProfile from olympia.users.models import UserProfile
from olympia.versions.models import Version from olympia.versions.models import Version
from . test_models import create_addon_file
pytestmark = pytest.mark.django_db pytestmark = pytest.mark.django_db
REVIEW_ADDON_STATUSES = (amo.STATUS_NOMINATED, amo.STATUS_LITE_AND_NOMINATED, REVIEW_FILES_STATUSES = (amo.STATUS_PUBLIC, amo.STATUS_DISABLED)
amo.STATUS_UNREVIEWED)
REVIEW_FILES_STATUSES = (amo.STATUS_PUBLIC,
amo.STATUS_DISABLED, amo.STATUS_LITE)
class TestViewPendingQueueTable(TestCase): class TestViewPendingQueueTable(TestCase):
@ -256,7 +251,7 @@ class TestReviewHelper(TestCase):
def get_data(self): def get_data(self):
return {'comments': 'foo', 'addon_files': self.version.files.all(), return {'comments': 'foo', 'addon_files': self.version.files.all(),
'action': 'prelim', 'operating_systems': 'osx', 'action': 'public', 'operating_systems': 'osx',
'applications': 'Firefox'} 'applications': 'Firefox'}
def get_helper(self): def get_helper(self):
@ -278,11 +273,6 @@ class TestReviewHelper(TestCase):
def test_type_nominated(self): def test_type_nominated(self):
assert self.setup_type(amo.STATUS_NOMINATED) == 'nominated' assert self.setup_type(amo.STATUS_NOMINATED) == 'nominated'
assert self.setup_type(amo.STATUS_LITE_AND_NOMINATED) == 'nominated'
def test_type_preliminary(self):
assert self.setup_type(amo.STATUS_UNREVIEWED) == 'preliminary'
assert self.setup_type(amo.STATUS_LITE) == 'preliminary'
def test_type_pending(self): def test_type_pending(self):
assert self.setup_type(amo.STATUS_PENDING) == 'pending' assert self.setup_type(amo.STATUS_PENDING) == 'pending'
@ -302,9 +292,8 @@ class TestReviewHelper(TestCase):
assert self.helper.handler.__class__ == helpers.ReviewFiles assert self.helper.handler.__class__ == helpers.ReviewFiles
def test_review_addon(self): def test_review_addon(self):
for status in REVIEW_ADDON_STATUSES: self.setup_data(status=amo.STATUS_NOMINATED)
self.setup_data(status=status) assert self.helper.handler.__class__ == helpers.ReviewAddon
assert self.helper.handler.__class__ == helpers.ReviewAddon
def test_process_action_none(self): def test_process_action_none(self):
self.helper.set_data({'action': 'foo'}) self.helper.set_data({'action': 'foo'})
@ -338,57 +327,18 @@ class TestReviewHelper(TestCase):
for k, v in actions.items(): for k, v in actions.items():
assert unicode(v['details']), "Missing details for: %s" % k assert unicode(v['details']), "Missing details for: %s" % k
def get_action_details(self, status, action):
self.file.update(status=amo.STATUS_UNREVIEWED)
self.addon.update(status=status)
return unicode(self.get_helper().actions[action]['details'])
def test_action_changes(self):
assert (self.get_action_details(amo.STATUS_LITE, 'reject')[:26] ==
'This will reject the files')
assert (self.get_action_details(amo.STATUS_UNREVIEWED,
'reject')[:27] == 'This will reject the add-on')
assert (self.get_action_details(amo.STATUS_UNREVIEWED,
'prelim')[:25] == 'This will mark the add-on')
assert (self.get_action_details(amo.STATUS_NOMINATED, 'prelim')[:25] ==
'This will mark the add-on')
assert (self.get_action_details(amo.STATUS_LITE, 'prelim')[:24] ==
'This will mark the files')
assert (self.get_action_details(amo.STATUS_LITE_AND_NOMINATED,
'prelim')[:27] == 'This will retain the add-on')
assert (self.get_action_details(amo.STATUS_NULL, 'info')[:41] ==
'Use this form to request more information')
assert (self.get_action_details(amo.STATUS_NOMINATED,
'public')[-31:] == 'they are reviewed by an editor.')
assert (self.get_action_details(amo.STATUS_PUBLIC, 'public')[-29:] ==
'to appear on the public site.')
def get_review_actions(self, addon_status, file_status): def get_review_actions(self, addon_status, file_status):
self.file.update(status=file_status) self.file.update(status=file_status)
self.addon.update(status=addon_status) self.addon.update(status=addon_status)
return self.get_helper().actions return self.get_helper().actions
def test_actions_full_nominated(self): def test_actions_full_nominated(self):
expected = ['public', 'prelim', 'reject', 'info', 'super', 'comment']
assert self.get_review_actions(
addon_status=amo.STATUS_NOMINATED,
file_status=amo.STATUS_UNREVIEWED).keys() == expected
@override_flag('no-prelim-review', active=True)
def test_actions_full_nominated_no_prelim(self):
expected = ['public', 'reject', 'info', 'super', 'comment'] expected = ['public', 'reject', 'info', 'super', 'comment']
assert self.get_review_actions( assert self.get_review_actions(
addon_status=amo.STATUS_NOMINATED, addon_status=amo.STATUS_NOMINATED,
file_status=amo.STATUS_UNREVIEWED).keys() == expected file_status=amo.STATUS_UNREVIEWED).keys() == expected
def test_actions_full_update(self): def test_actions_full_update(self):
expected = ['public', 'prelim', 'reject', 'info', 'super', 'comment']
assert self.get_review_actions(
addon_status=amo.STATUS_PUBLIC,
file_status=amo.STATUS_UNREVIEWED).keys() == expected
@override_flag('no-prelim-review', active=True)
def test_actions_full_update_no_prelim(self):
expected = ['public', 'reject', 'info', 'super', 'comment'] expected = ['public', 'reject', 'info', 'super', 'comment']
assert self.get_review_actions( assert self.get_review_actions(
addon_status=amo.STATUS_PUBLIC, addon_status=amo.STATUS_PUBLIC,
@ -396,45 +346,12 @@ class TestReviewHelper(TestCase):
def test_actions_full_nonpending(self): def test_actions_full_nonpending(self):
expected = ['info', 'super', 'comment'] expected = ['info', 'super', 'comment']
f_statuses = [amo.STATUS_PUBLIC, amo.STATUS_DISABLED, amo.STATUS_LITE] f_statuses = [amo.STATUS_PUBLIC, amo.STATUS_DISABLED]
for file_status in f_statuses: for file_status in f_statuses:
assert self.get_review_actions( assert self.get_review_actions(
addon_status=amo.STATUS_PUBLIC, addon_status=amo.STATUS_PUBLIC,
file_status=file_status).keys() == expected file_status=file_status).keys() == expected
def test_actions_prelim_pending(self):
expected = ['prelim', 'reject', 'info', 'super', 'comment']
assert self.get_review_actions(
addon_status=amo.STATUS_UNREVIEWED,
file_status=amo.STATUS_UNREVIEWED).keys() == expected
def test_actions_prelim_update(self):
expected = ['prelim', 'reject', 'info', 'super', 'comment']
assert self.get_review_actions(
addon_status=amo.STATUS_LITE,
file_status=amo.STATUS_UNREVIEWED).keys() == expected
def test_actions_prelim_nonpending(self):
expected = ['info', 'super', 'comment']
f_statuses = [amo.STATUS_DISABLED, amo.STATUS_LITE]
for file_status in f_statuses:
assert self.get_review_actions(
addon_status=amo.STATUS_LITE,
file_status=file_status).keys() == expected
def test_actions_prelim_upgrade_to_full(self):
expected = ['public', 'prelim', 'reject', 'info', 'super', 'comment']
assert self.get_review_actions(
addon_status=amo.STATUS_LITE_AND_NOMINATED,
file_status=amo.STATUS_LITE).keys() == expected
@override_flag('no-prelim-review', active=True)
def test_actions_prelim_upgrade_to_full_no_prelim(self):
expected = ['public', 'reject', 'info', 'super', 'comment']
assert self.get_review_actions(
addon_status=amo.STATUS_LITE_AND_NOMINATED,
file_status=amo.STATUS_LITE).keys() == expected
def test_set_files(self): def test_set_files(self):
self.file.update(datestatuschanged=yesterday) self.file.update(datestatuschanged=yesterday)
self.helper.set_data({'addon_files': self.version.files.all()}) self.helper.set_data({'addon_files': self.version.files.all()})
@ -471,13 +388,11 @@ class TestReviewHelper(TestCase):
def test_notify_email(self): def test_notify_email(self):
self.helper.set_data(self.get_data()) self.helper.set_data(self.get_data())
base_fragment = 'reply to this email or join #amo-editors' base_fragment = 'reply to this email or join #amo-editors'
for template in ['nominated_to_nominated', 'nominated_to_preliminary', for template in ('nominated_to_nominated',
'nominated_to_public', 'nominated_to_sandbox', 'nominated_to_public', 'nominated_to_sandbox',
'pending_to_preliminary', 'pending_to_public', 'pending_to_public', 'pending_to_sandbox',
'pending_to_sandbox', 'preliminary_to_preliminary',
'author_super_review', 'unlisted_to_reviewed', 'author_super_review', 'unlisted_to_reviewed',
'unlisted_to_reviewed_auto', 'unlisted_to_reviewed_auto', 'unlisted_to_sandbox'):
'unlisted_to_sandbox']:
mail.outbox = [] mail.outbox = []
self.helper.handler.notify_email(template, 'Sample subject %s, %s') self.helper.handler.notify_email(template, 'Sample subject %s, %s')
assert len(mail.outbox) == 1 assert len(mail.outbox) == 1
@ -493,13 +408,11 @@ class TestReviewHelper(TestCase):
reply_email = ( reply_email = (
'reviewreply+%s@%s' % (uuid, settings.INBOUND_EMAIL_DOMAIN)) 'reviewreply+%s@%s' % (uuid, settings.INBOUND_EMAIL_DOMAIN))
for template in ['nominated_to_nominated', 'nominated_to_preliminary', for template in ('nominated_to_nominated', 'nominated_to_public',
'nominated_to_public', 'nominated_to_sandbox', 'nominated_to_sandbox', 'pending_to_public',
'pending_to_preliminary', 'pending_to_public', 'pending_to_sandbox', 'author_super_review',
'pending_to_sandbox', 'preliminary_to_preliminary', 'unlisted_to_reviewed', 'unlisted_to_reviewed_auto',
'author_super_review', 'unlisted_to_reviewed', 'unlisted_to_sandbox'):
'unlisted_to_reviewed_auto',
'unlisted_to_sandbox']:
mail.outbox = [] mail.outbox = []
self.helper.handler.notify_email(template, 'Sample subject %s, %s') self.helper.handler.notify_email(template, 'Sample subject %s, %s')
assert len(mail.outbox) == 1 assert len(mail.outbox) == 1
@ -509,16 +422,12 @@ class TestReviewHelper(TestCase):
def test_email_links(self): def test_email_links(self):
expected = { expected = {
'nominated_to_nominated': 'addon_url', 'nominated_to_nominated': 'addon_url',
'nominated_to_preliminary': 'addon_url',
'nominated_to_public': 'addon_url', 'nominated_to_public': 'addon_url',
'nominated_to_sandbox': 'dev_versions_url', 'nominated_to_sandbox': 'dev_versions_url',
'pending_to_preliminary': 'addon_url',
'pending_to_public': 'addon_url', 'pending_to_public': 'addon_url',
'pending_to_sandbox': 'dev_versions_url', 'pending_to_sandbox': 'dev_versions_url',
'preliminary_to_preliminary': 'addon_url',
'unlisted_to_reviewed': 'dev_versions_url', 'unlisted_to_reviewed': 'dev_versions_url',
'unlisted_to_reviewed_auto': 'dev_versions_url', 'unlisted_to_reviewed_auto': 'dev_versions_url',
'unlisted_to_sandbox': 'dev_versions_url' 'unlisted_to_sandbox': 'dev_versions_url'
@ -539,7 +448,9 @@ class TestReviewHelper(TestCase):
mail.outbox = [] mail.outbox = []
ActivityLog.objects.for_addons(self.helper.addon).delete() ActivityLog.objects.for_addons(self.helper.addon).delete()
self.addon.update(status=status, is_listed=is_listed) self.addon.update(status=status, is_listed=is_listed)
self.file.update(status=status) file_status = (amo.STATUS_UNREVIEWED if status == amo.STATUS_NOMINATED
else status)
self.file.update(status=file_status)
self.helper = self.get_helper() self.helper = self.get_helper()
data = self.get_data().copy() data = self.get_data().copy()
for key in delete: for key in delete:
@ -595,23 +506,21 @@ class TestReviewHelper(TestCase):
assert 'Your add-on, Delicious Bookmarks ' in mail.outbox[0].body assert 'Your add-on, Delicious Bookmarks ' in mail.outbox[0].body
def test_nomination_to_public_no_files(self): def test_nomination_to_public_no_files(self):
for status in helpers.NOMINATED_STATUSES: self.setup_data(amo.STATUS_NOMINATED, ['addon_files'])
self.setup_data(status, ['addon_files']) self.helper.handler.process_public()
self.helper.handler.process_public()
assert self.addon.versions.all()[0].files.all()[0].status == ( assert self.addon.versions.all()[0].files.all()[0].status == (
amo.STATUS_PUBLIC) amo.STATUS_PUBLIC)
def test_nomination_to_public_and_current_version(self): def test_nomination_to_public_and_current_version(self):
for status in helpers.NOMINATED_STATUSES: self.setup_data(amo.STATUS_NOMINATED, ['addon_files'])
self.setup_data(status, ['addon_files']) self.addon = Addon.objects.get(pk=3615)
self.addon = Addon.objects.get(pk=3615) self.addon.update(_current_version=None)
self.addon.update(_current_version=None) assert not self.addon.current_version
assert not self.addon.current_version
self.helper.handler.process_public() self.helper.handler.process_public()
self.addon = Addon.objects.get(pk=3615) self.addon = Addon.objects.get(pk=3615)
assert self.addon.current_version assert self.addon.current_version
def test_nomination_to_public_new_addon(self): def test_nomination_to_public_new_addon(self):
""" Make sure new add-ons can be made public (bug 637959) """ """ Make sure new add-ons can be made public (bug 637959) """
@ -643,199 +552,107 @@ class TestReviewHelper(TestCase):
@patch('olympia.editors.helpers.sign_file') @patch('olympia.editors.helpers.sign_file')
def test_nomination_to_public(self, sign_mock): def test_nomination_to_public(self, sign_mock):
for status in helpers.NOMINATED_STATUSES: sign_mock.reset()
sign_mock.reset() self.setup_data(amo.STATUS_NOMINATED)
self.setup_data(status) with self.settings(SIGNING_SERVER='full'):
with self.settings(SIGNING_SERVER='full'): self.helper.handler.process_public()
self.helper.handler.process_public()
assert self.addon.status == amo.STATUS_PUBLIC assert self.addon.status == amo.STATUS_PUBLIC
assert self.addon.versions.all()[0].files.all()[0].status == ( assert self.addon.versions.all()[0].files.all()[0].status == (
amo.STATUS_PUBLIC) amo.STATUS_PUBLIC)
assert len(mail.outbox) == 1 assert len(mail.outbox) == 1
assert mail.outbox[0].subject == ( assert mail.outbox[0].subject == (
'%s Fully Reviewed' % self.preamble) '%s Fully Reviewed' % self.preamble)
assert 'has been fully reviewed' in mail.outbox[0].body assert 'has been fully reviewed' in mail.outbox[0].body
sign_mock.assert_called_with(self.file, 'full') sign_mock.assert_called_with(self.file, 'full')
assert storage.exists(self.file.mirror_file_path) assert storage.exists(self.file.mirror_file_path)
assert self.check_log_count(amo.LOG.APPROVE_VERSION.id) == 1 assert self.check_log_count(amo.LOG.APPROVE_VERSION.id) == 1
self._check_score(amo.REVIEWED_ADDON_FULL) self._check_score(amo.REVIEWED_ADDON_FULL)
@patch('olympia.editors.helpers.sign_file') @patch('olympia.editors.helpers.sign_file')
def test_nomination_to_public_unlisted(self, sign_mock): def test_nomination_to_public_unlisted(self, sign_mock):
for status in helpers.NOMINATED_STATUSES: sign_mock.reset()
sign_mock.reset() self.setup_data(amo.STATUS_NOMINATED, is_listed=False)
self.setup_data(status, is_listed=False) with self.settings(SIGNING_SERVER='full'):
with self.settings(SIGNING_SERVER='full'): self.helper.handler.process_public()
self.helper.handler.process_public()
assert self.addon.status == amo.STATUS_PUBLIC assert self.addon.status == amo.STATUS_PUBLIC
assert self.addon.versions.all()[0].files.all()[0].status == ( assert self.addon.versions.all()[0].files.all()[0].status == (
amo.STATUS_PUBLIC) amo.STATUS_PUBLIC)
assert len(mail.outbox) == 1 assert len(mail.outbox) == 1
assert mail.outbox[0].subject == ( assert mail.outbox[0].subject == (
'%s signed and ready to download' % self.preamble) '%s signed and ready to download' % self.preamble)
assert 'has been reviewed and is now signed' in mail.outbox[0].body assert 'has been reviewed and is now signed' in mail.outbox[0].body
sign_mock.assert_called_with(self.file, 'full') sign_mock.assert_called_with(self.file, 'full')
assert storage.exists(self.file.mirror_file_path) assert storage.exists(self.file.mirror_file_path)
assert self.check_log_count(amo.LOG.APPROVE_VERSION.id) == 1 assert self.check_log_count(amo.LOG.APPROVE_VERSION.id) == 1
self._check_score(amo.REVIEWED_ADDON_FULL) self._check_score(amo.REVIEWED_ADDON_FULL)
@patch('olympia.editors.helpers.sign_file') @patch('olympia.editors.helpers.sign_file')
def test_nomination_to_public_failed_signing(self, sign_mock): def test_nomination_to_public_failed_signing(self, sign_mock):
sign_mock.side_effect = Exception sign_mock.side_effect = Exception
for status in helpers.NOMINATED_STATUSES: sign_mock.reset()
sign_mock.reset() self.setup_data(amo.STATUS_NOMINATED)
self.setup_data(status) with self.settings(SIGNING_SERVER='full'):
with self.settings(SIGNING_SERVER='full'):
with self.assertRaises(Exception):
self.helper.handler.process_public()
# Status unchanged.
assert self.addon.status == status
assert self.addon.versions.all()[0].files.all()[0].status == status
assert len(mail.outbox) == 0
assert self.check_log_count(amo.LOG.APPROVE_VERSION.id) == 0
@patch('olympia.editors.helpers.sign_file')
def test_nomination_to_preliminary(self, sign_mock):
for status in helpers.NOMINATED_STATUSES:
sign_mock.reset()
self.setup_data(status)
with self.settings(PRELIMINARY_SIGNING_SERVER='prelim'):
self.helper.handler.process_preliminary()
assert self.addon.status == amo.STATUS_LITE
assert self.addon.versions.all()[0].files.all()[0].status == (
amo.STATUS_LITE)
assert len(mail.outbox) == 1
assert mail.outbox[0].subject == (
'%s Preliminary Reviewed' % self.preamble)
assert 'has been granted preliminary review' in mail.outbox[0].body
sign_mock.assert_called_with(self.file, 'prelim')
assert storage.exists(self.file.mirror_file_path)
assert self.check_log_count(amo.LOG.PRELIMINARY_VERSION.id) == 1
self._check_score(amo.REVIEWED_ADDON_FULL)
@patch('olympia.editors.helpers.sign_file')
def test_nomination_to_preliminary_unlisted(self, sign_mock):
for status in helpers.NOMINATED_STATUSES:
sign_mock.reset()
self.setup_data(status, is_listed=False)
with self.settings(PRELIMINARY_SIGNING_SERVER='prelim'):
self.helper.handler.process_preliminary()
assert self.addon.status == amo.STATUS_LITE
assert self.addon.versions.all()[0].files.all()[0].status == (
amo.STATUS_LITE)
assert len(mail.outbox) == 1
assert mail.outbox[0].subject == (
'%s signed and ready to download' % self.preamble)
assert 'has been reviewed and is now signed' in mail.outbox[0].body
sign_mock.assert_called_with(self.file, 'prelim')
assert storage.exists(self.file.mirror_file_path)
assert self.check_log_count(amo.LOG.PRELIMINARY_VERSION.id) == 1
self._check_score(amo.REVIEWED_ADDON_FULL)
@patch('olympia.editors.helpers.sign_file')
def test_nomination_to_preliminary_unlisted_auto(self, sign_mock):
for status in helpers.NOMINATED_STATUSES:
sign_mock.reset()
self.setup_data(status, is_listed=False)
with self.settings(PRELIMINARY_SIGNING_SERVER='prelim'):
self.helper.handler.process_preliminary(auto_validation=True)
assert self.addon.status == amo.STATUS_LITE
assert self.addon.versions.all()[0].files.all()[0].status == (
amo.STATUS_LITE)
assert len(mail.outbox) == 1
assert mail.outbox[0].subject == (
'%s signed and ready to download' % self.preamble)
assert 'has passed our automatic tests' in mail.outbox[0].body
sign_mock.assert_called_with(self.file, 'prelim')
assert storage.exists(self.file.mirror_file_path)
assert self.check_log_count(amo.LOG.PRELIMINARY_VERSION.id) == 1
assert not ReviewerScore.objects.all()
@patch('olympia.editors.helpers.sign_file')
def test_nomination_to_preliminary_failed_signing(self, sign_mock):
sign_mock.side_effect = Exception
for status in helpers.NOMINATED_STATUSES:
sign_mock.reset()
self.setup_data(status)
with self.assertRaises(Exception): with self.assertRaises(Exception):
self.helper.handler.process_preliminary() self.helper.handler.process_public()
# Status unchanged. # Status unchanged.
assert self.addon.status == status assert self.addon.status == amo.STATUS_NOMINATED
assert self.addon.versions.all()[0].files.all()[0].status == status assert self.addon.versions.all()[0].files.all()[0].status == (
amo.STATUS_UNREVIEWED)
assert len(mail.outbox) == 0 assert len(mail.outbox) == 0
assert self.check_log_count(amo.LOG.APPROVE_VERSION.id) == 0 assert self.check_log_count(amo.LOG.APPROVE_VERSION.id) == 0
@patch('olympia.editors.helpers.sign_file') @patch('olympia.editors.helpers.sign_file')
def test_nomination_to_sandbox(self, sign_mock): def test_nomination_to_sandbox(self, sign_mock):
for status in helpers.NOMINATED_STATUSES: self.setup_data(amo.STATUS_NOMINATED)
self.setup_data(status) self.helper.handler.process_sandbox()
self.helper.handler.process_sandbox()
assert self.addon.status == amo.STATUS_NULL assert self.addon.status == amo.STATUS_NULL
assert self.addon.versions.all()[0].files.all()[0].status == ( assert self.addon.versions.all()[0].files.all()[0].status == (
amo.STATUS_DISABLED) amo.STATUS_DISABLED)
assert len(mail.outbox) == 1 assert len(mail.outbox) == 1
assert mail.outbox[0].subject == ( assert mail.outbox[0].subject == (
'%s didn\'t pass review' % self.preamble) '%s didn\'t pass review' % self.preamble)
assert 'did not meet the criteria' in mail.outbox[0].body assert 'did not meet the criteria' in mail.outbox[0].body
assert not sign_mock.called assert not sign_mock.called
assert not storage.exists(self.file.mirror_file_path) assert not storage.exists(self.file.mirror_file_path)
assert self.check_log_count(amo.LOG.REJECT_VERSION.id) == 1 assert self.check_log_count(amo.LOG.REJECT_VERSION.id) == 1
@patch('olympia.editors.helpers.sign_file') @patch('olympia.editors.helpers.sign_file')
def test_nomination_to_sandbox_unlisted(self, sign_mock): def test_nomination_to_sandbox_unlisted(self, sign_mock):
for status in helpers.NOMINATED_STATUSES: self.setup_data(amo.STATUS_NOMINATED, is_listed=False)
self.setup_data(status, is_listed=False) self.helper.handler.process_sandbox()
self.helper.handler.process_sandbox()
assert self.addon.status == amo.STATUS_NULL assert self.addon.status == amo.STATUS_NULL
assert self.addon.versions.all()[0].files.all()[0].status == ( assert self.addon.versions.all()[0].files.all()[0].status == (
amo.STATUS_DISABLED) amo.STATUS_DISABLED)
assert len(mail.outbox) == 1 assert len(mail.outbox) == 1
assert mail.outbox[0].subject == ( assert mail.outbox[0].subject == (
'%s didn\'t pass review' % self.preamble) '%s didn\'t pass review' % self.preamble)
assert 'didn\'t pass review' in mail.outbox[0].body assert 'didn\'t pass review' in mail.outbox[0].body
assert not sign_mock.called assert not sign_mock.called
assert not storage.exists(self.file.mirror_file_path) assert not storage.exists(self.file.mirror_file_path)
assert self.check_log_count(amo.LOG.REJECT_VERSION.id) == 1 assert self.check_log_count(amo.LOG.REJECT_VERSION.id) == 1
def test_email_unicode_monster(self): def test_email_unicode_monster(self):
self.addon.name = u'TaobaoShopping淘宝网导航按钮' self.addon.name = u'TaobaoShopping淘宝网导航按钮'
self.addon.save() self.addon.save()
self.setup_data(helpers.NOMINATED_STATUSES[0]) self.setup_data(amo.STATUS_NOMINATED)
self.helper.handler.process_sandbox() self.helper.handler.process_sandbox()
assert u'TaobaoShopping淘宝网导航按钮' in mail.outbox[0].subject assert u'TaobaoShopping淘宝网导航按钮' in mail.outbox[0].subject
@ -846,221 +663,70 @@ class TestReviewHelper(TestCase):
assert url in mail.outbox[1].body assert url in mail.outbox[1].body
def test_nomination_to_super_review(self): def test_nomination_to_super_review(self):
for status in helpers.NOMINATED_STATUSES: self.setup_data(amo.STATUS_NOMINATED)
self.setup_data(status) self.helper.handler.process_super_review()
self.helper.handler.process_super_review()
assert self.addon.admin_review assert self.addon.admin_review
assert len(mail.outbox) == 2 assert len(mail.outbox) == 2
assert mail.outbox[1].subject == ( assert mail.outbox[1].subject == (
'Super review requested: Delicious Bookmarks') 'Super review requested: Delicious Bookmarks')
assert mail.outbox[0].subject == ( assert mail.outbox[0].subject == (
('Mozilla Add-ons: Delicious Bookmarks 2.1.072 flagged for ' ('Mozilla Add-ons: Delicious Bookmarks 2.1.072 flagged for '
'Admin Review')) 'Admin Review'))
assert self.check_log_count(amo.LOG.REQUEST_SUPER_REVIEW.id) == 1 assert self.check_log_count(amo.LOG.REQUEST_SUPER_REVIEW.id) == 1
def test_unreviewed_to_public(self):
self.setup_data(amo.STATUS_UNREVIEWED)
self.assertRaises(AssertionError,
self.helper.handler.process_public)
def test_lite_to_public(self):
self.setup_data(amo.STATUS_LITE)
self.assertRaises(AssertionError,
self.helper.handler.process_public)
@patch('olympia.editors.helpers.sign_file')
def test_preliminary_to_preliminary(self, sign_mock):
for status in helpers.PRELIMINARY_STATUSES:
self.setup_data(status)
self.helper.handler.process_preliminary()
for file in self.helper.handler.data['addon_files']:
assert file.status == amo.STATUS_LITE
assert len(mail.outbox) == 1
assert mail.outbox[0].subject == (
'%s Preliminary Reviewed' % self.preamble)
assert 'has been preliminarily reviewed' in mail.outbox[0].body
assert sign_mock.called
assert storage.exists(self.file.mirror_file_path)
assert self.check_log_count(amo.LOG.PRELIMINARY_VERSION.id) == 1
self._check_score(amo.REVIEWED_ADDON_PRELIM)
@patch('olympia.editors.helpers.sign_file')
def test_preliminary_to_preliminary_unlisted(self, sign_mock):
for status in helpers.PRELIMINARY_STATUSES:
self.setup_data(status, is_listed=False)
self.helper.handler.process_preliminary()
for file in self.helper.handler.data['addon_files']:
assert file.status == amo.STATUS_LITE
assert len(mail.outbox) == 1
assert mail.outbox[0].subject == (
'%s signed and ready to download' % self.preamble)
assert 'has been reviewed and is now signed' in mail.outbox[0].body
assert sign_mock.called
assert storage.exists(self.file.mirror_file_path)
assert self.check_log_count(amo.LOG.PRELIMINARY_VERSION.id) == 1
self._check_score(amo.REVIEWED_ADDON_PRELIM)
@patch('olympia.editors.helpers.sign_file')
def test_preliminary_to_preliminary_unlisted_auto(self, sign_mock):
for status in helpers.PRELIMINARY_STATUSES:
self.setup_data(status, is_listed=False)
self.helper.handler.process_preliminary(auto_validation=True)
for file in self.helper.handler.data['addon_files']:
assert file.status == amo.STATUS_LITE
assert len(mail.outbox) == 1
assert mail.outbox[0].subject == (
'%s signed and ready to download' % self.preamble)
assert 'has passed our automatic tests' in mail.outbox[0].body
assert sign_mock.called
assert storage.exists(self.file.mirror_file_path)
assert self.check_log_count(amo.LOG.PRELIMINARY_VERSION.id) == 1
assert not ReviewerScore.objects.all()
@patch('olympia.editors.helpers.sign_file')
def test_preliminary_to_sandbox(self, sign_mock):
for status in [amo.STATUS_UNREVIEWED, amo.STATUS_LITE_AND_NOMINATED]:
self.setup_data(status)
self.helper.handler.process_sandbox()
for file in self.helper.handler.data['addon_files']:
assert file.status == amo.STATUS_DISABLED
assert len(mail.outbox) == 1
assert mail.outbox[0].subject == (
'%s didn\'t pass review' % self.preamble)
assert 'did not meet the criteria' in mail.outbox[0].body
assert not sign_mock.called
assert not storage.exists(self.file.mirror_file_path)
assert self.check_log_count(amo.LOG.REJECT_VERSION.id) == 1
@patch('olympia.editors.helpers.sign_file')
def test_preliminary_to_sandbox_unlisted(self, sign_mock):
for status in [amo.STATUS_UNREVIEWED, amo.STATUS_LITE_AND_NOMINATED]:
self.setup_data(status, is_listed=False)
self.helper.handler.process_sandbox()
for file in self.helper.handler.data['addon_files']:
assert file.status == amo.STATUS_DISABLED
assert len(mail.outbox) == 1
assert mail.outbox[0].subject == (
'%s didn\'t pass review' % self.preamble)
assert 'didn\'t pass review' in mail.outbox[0].body
assert not sign_mock.called
assert not storage.exists(self.file.mirror_file_path)
assert self.check_log_count(amo.LOG.REJECT_VERSION.id) == 1
def test_preliminary_upgrade_to_sandbox(self):
self.setup_data(amo.STATUS_LITE)
assert self.addon.status == amo.STATUS_LITE
assert self.file.status == amo.STATUS_LITE
a = create_addon_file(self.addon.name, '2.2', amo.STATUS_LITE,
amo.STATUS_UNREVIEWED)
self.version = a['version']
self.addon.update(status=amo.STATUS_LITE_AND_NOMINATED)
self.helper = self.get_helper()
self.helper.set_data(self.get_data())
self.helper.handler.process_sandbox()
assert self.addon.status == amo.STATUS_LITE
assert self.file.status == amo.STATUS_LITE
f = File.objects.get(pk=a['file'].id)
assert f.status == amo.STATUS_DISABLED
def test_preliminary_to_super_review(self):
for status in helpers.PRELIMINARY_STATUSES:
self.setup_data(status)
self.helper.handler.process_super_review()
assert self.addon.admin_review
assert len(mail.outbox) == 2
assert mail.outbox[1].subject == (
'Super review requested: Delicious Bookmarks')
assert mail.outbox[0].subject == (
('Mozilla Add-ons: Delicious Bookmarks 2.1.072 flagged for '
'Admin Review'))
assert self.check_log_count(amo.LOG.REQUEST_SUPER_REVIEW.id) == 1
def test_nomination_to_super_review_and_escalate(self): def test_nomination_to_super_review_and_escalate(self):
# Note we are changing the file status here. self.setup_data(amo.STATUS_NOMINATED)
for file_status in (amo.STATUS_PENDING, amo.STATUS_UNREVIEWED): self.file.update(status=amo.STATUS_UNREVIEWED)
self.setup_data(amo.STATUS_LITE) self.helper.handler.process_super_review()
self.file.update(status=file_status)
self.helper.handler.process_super_review()
assert self.addon.admin_review assert self.addon.admin_review
assert len(mail.outbox) == 2 assert len(mail.outbox) == 2
assert mail.outbox[1].subject == ( assert mail.outbox[1].subject == (
'Super review requested: Delicious Bookmarks') 'Super review requested: Delicious Bookmarks')
assert mail.outbox[0].subject == ( assert mail.outbox[0].subject == (
('Mozilla Add-ons: Delicious Bookmarks 2.1.072 flagged for ' ('Mozilla Add-ons: Delicious Bookmarks 2.1.072 flagged for '
'Admin Review')) 'Admin Review'))
assert self.check_log_count(amo.LOG.REQUEST_SUPER_REVIEW.id) == 1 assert self.check_log_count(amo.LOG.REQUEST_SUPER_REVIEW.id) == 1
@patch('olympia.editors.helpers.sign_file') @patch('olympia.editors.helpers.sign_file')
def test_pending_to_public(self, sign_mock): def test_pending_to_public(self, sign_mock):
for status in [amo.STATUS_NOMINATED, amo.STATUS_LITE_AND_NOMINATED]: self.setup_data(amo.STATUS_NOMINATED)
self.setup_data(status) self.create_paths()
self.create_paths() self.helper.handler.process_public()
self.helper.handler.process_public()
for file in self.helper.handler.data['addon_files']: for file in self.helper.handler.data['addon_files']:
assert file.status == amo.STATUS_PUBLIC assert file.status == amo.STATUS_PUBLIC
assert len(mail.outbox) == 1 assert len(mail.outbox) == 1
assert mail.outbox[0].subject == ( assert mail.outbox[0].subject == (
'%s Fully Reviewed' % self.preamble) '%s Fully Reviewed' % self.preamble)
assert 'has been fully reviewed' in mail.outbox[0].body assert 'has been fully reviewed' in mail.outbox[0].body
assert sign_mock.called assert sign_mock.called
assert storage.exists(self.file.mirror_file_path) assert storage.exists(self.file.mirror_file_path)
assert self.check_log_count(amo.LOG.APPROVE_VERSION.id) == 1 assert self.check_log_count(amo.LOG.APPROVE_VERSION.id) == 1
if status == amo.STATUS_PUBLIC:
self._check_score(amo.REVIEWED_ADDON_UPDATE)
@patch('olympia.editors.helpers.sign_file') @patch('olympia.editors.helpers.sign_file')
def test_pending_to_public_unlisted(self, sign_mock): def test_pending_to_public_unlisted(self, sign_mock):
for status in [amo.STATUS_NOMINATED, amo.STATUS_LITE_AND_NOMINATED]: self.setup_data(amo.STATUS_NOMINATED, is_listed=False)
self.setup_data(status, is_listed=False) self.create_paths()
self.create_paths() self.helper.handler.process_public()
self.helper.handler.process_public()
for file in self.helper.handler.data['addon_files']: for file in self.helper.handler.data['addon_files']:
assert file.status == amo.STATUS_PUBLIC assert file.status == amo.STATUS_PUBLIC
assert len(mail.outbox) == 1 assert len(mail.outbox) == 1
assert mail.outbox[0].subject == ( assert mail.outbox[0].subject == (
'%s signed and ready to download' % self.preamble) '%s signed and ready to download' % self.preamble)
assert 'has been reviewed and is now signed' in mail.outbox[0].body assert 'has been reviewed and is now signed' in mail.outbox[0].body
assert sign_mock.called assert sign_mock.called
assert storage.exists(self.file.mirror_file_path) assert storage.exists(self.file.mirror_file_path)
assert self.check_log_count(amo.LOG.APPROVE_VERSION.id) == 1 assert self.check_log_count(amo.LOG.APPROVE_VERSION.id) == 1
if status == amo.STATUS_PUBLIC:
self._check_score(amo.REVIEWED_ADDON_UPDATE)
@patch('olympia.editors.helpers.sign_file') @patch('olympia.editors.helpers.sign_file')
def test_pending_to_sandbox(self, sign_mock): def test_pending_to_sandbox(self, sign_mock):
@ -1146,27 +812,19 @@ class TestReviewHelper(TestCase):
('Mozilla Add-ons: Delicious Bookmarks 2.1.072 flagged for ' ('Mozilla Add-ons: Delicious Bookmarks 2.1.072 flagged for '
'Admin Review')) 'Admin Review'))
def test_nominated_review_time_set(self): def test_nominated_review_time_set_version(self):
for status in REVIEW_ADDON_STATUSES: for process in ('process_sandbox', 'process_public'):
for process in ['process_sandbox', 'process_preliminary', self.version.update(reviewed=None)
'process_public']: self.setup_data(amo.STATUS_NOMINATED)
if (status == amo.STATUS_UNREVIEWED and getattr(self.helper.handler, process)()
process == 'process_public'): assert self.version.reviewed
continue
self.version.update(reviewed=None)
self.setup_data(status)
getattr(self.helper.handler, process)()
assert self.version.reviewed, ('Reviewed for status %r, %s()'
% (status, process))
def test_preliminary_review_time_set(self): def test_nominated_review_time_set_file(self):
for status in amo.UNDER_REVIEW_STATUSES: for process in ('process_sandbox', 'process_public'):
for process in ['process_sandbox', 'process_preliminary']: self.file.update(reviewed=None)
self.file.update(reviewed=None) self.setup_data(amo.STATUS_NOMINATED)
self.setup_data(status) getattr(self.helper.handler, process)()
getattr(self.helper.handler, process)() assert File.objects.get(pk=self.file.pk).reviewed
assert File.objects.get(pk=self.file.pk).reviewed, (
'Reviewed for status %r, %s()' % (status, process))
def test_page_title_unicode(): def test_page_title_unicode():

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

@ -16,8 +16,8 @@ from olympia.applications.models import AppVersion
from olympia.editors.models import ( from olympia.editors.models import (
EditorSubscription, RereviewQueueTheme, ReviewerScore, send_notifications, EditorSubscription, RereviewQueueTheme, ReviewerScore, send_notifications,
ViewFullReviewQueue, ViewPendingQueue, ViewFullReviewQueue, ViewPendingQueue,
ViewPreliminaryQueue, ViewUnlistedAllList, ViewUnlistedFullReviewQueue, ViewUnlistedAllList, ViewUnlistedFullReviewQueue,
ViewUnlistedPendingQueue, ViewUnlistedPreliminaryQueue) ViewUnlistedPendingQueue)
from olympia.users.models import UserProfile from olympia.users.models import UserProfile
@ -233,16 +233,6 @@ class TestFullReviewQueue(TestQueue):
amo.STATUS_NOMINATED, amo.STATUS_UNREVIEWED, amo.STATUS_NOMINATED, amo.STATUS_UNREVIEWED,
listed=self.listed, **kw) listed=self.listed, **kw)
def test_lite_review_addons_also_shows_up(self):
create_addon_file('Full', '0.1',
amo.STATUS_NOMINATED, amo.STATUS_UNREVIEWED,
listed=self.listed)
create_addon_file('Lite', '0.1',
amo.STATUS_LITE_AND_NOMINATED,
amo.STATUS_LITE, listed=self.listed)
assert sorted(q.addon_name for q in self.Queue.objects.all()) == (
['Full', 'Lite'])
def test_waiting_time(self): def test_waiting_time(self):
self.new_file(name='Addon 1', version=u'0.1') self.new_file(name='Addon 1', version=u'0.1')
Version.objects.update(nomination=datetime.utcnow()) Version.objects.update(nomination=datetime.utcnow())
@ -252,41 +242,6 @@ class TestFullReviewQueue(TestQueue):
assert row.waiting_time_hours is not None assert row.waiting_time_hours is not None
class TestPreliminaryQueue(TestQueue):
__test__ = True
Queue = ViewPreliminaryQueue
def new_file(self, name=u'Preliminary', version=u'1.0',
addon_status=amo.STATUS_LITE,
file_status=amo.STATUS_UNREVIEWED, **kw):
return create_addon_file(name, version, addon_status, file_status,
listed=self.listed, **kw)
def new_search_ext(self, name, version, **kw):
return create_search_ext(name, version,
amo.STATUS_LITE, amo.STATUS_UNREVIEWED,
listed=self.listed, **kw)
def test_unreviewed_addons_are_in_q(self):
create_addon_file('Lite', '0.1',
amo.STATUS_LITE, amo.STATUS_UNREVIEWED,
listed=self.listed)
create_addon_file('Unreviewed', '0.1',
amo.STATUS_UNREVIEWED, amo.STATUS_UNREVIEWED,
listed=self.listed)
assert sorted(q.addon_name for q in self.Queue.objects.all()) == (
['Lite', 'Unreviewed'])
def test_waiting_time(self):
self.new_file(name='Addon 1', version=u'0.1')
Version.objects.update(created=datetime.utcnow())
row = self.Queue.objects.all()[0]
assert row.waiting_time_days == 0
# Time zone might be off due to your MySQL install, hard to test this.
assert row.waiting_time_min is not None
assert row.waiting_time_hours is not None
class TestUnlistedPendingQueue(TestPendingQueue): class TestUnlistedPendingQueue(TestPendingQueue):
Queue = ViewUnlistedPendingQueue Queue = ViewUnlistedPendingQueue
listed = False listed = False
@ -297,27 +252,18 @@ class TestUnlistedFullReviewQueue(TestFullReviewQueue):
listed = False listed = False
class TestUnlistedPreliminaryQueue(TestPreliminaryQueue):
Queue = ViewUnlistedPreliminaryQueue
listed = False
class TestUnlistedAllList(TestCase): class TestUnlistedAllList(TestCase):
Queue = ViewUnlistedAllList Queue = ViewUnlistedAllList
listed = False listed = False
fixtures = ['base/users'] fixtures = ['base/users']
def new_file(self, name=u'Preliminary', version=u'1.0', def new_file(self, name=u'Nominated', version=u'1.0',
addon_status=amo.STATUS_LITE, addon_status=amo.STATUS_NOMINATED,
file_status=amo.STATUS_UNREVIEWED, **kw): file_status=amo.STATUS_UNREVIEWED, **kw):
return create_addon_file(name, version, addon_status, file_status, return create_addon_file(name, version, addon_status, file_status,
listed=self.listed, **kw) listed=self.listed, **kw)
def test_all_addons_are_in_q(self): def test_all_addons_are_in_q(self):
self.new_file('Lite', addon_status=amo.STATUS_LITE,
file_status=amo.STATUS_UNREVIEWED)
self.new_file('Unreviewed', addon_status=amo.STATUS_UNREVIEWED,
file_status=amo.STATUS_UNREVIEWED)
self.new_file('Public', addon_status=amo.STATUS_PUBLIC, self.new_file('Public', addon_status=amo.STATUS_PUBLIC,
file_status=amo.STATUS_PUBLIC) file_status=amo.STATUS_PUBLIC)
self.new_file('Nominated', addon_status=amo.STATUS_NOMINATED, self.new_file('Nominated', addon_status=amo.STATUS_NOMINATED,
@ -325,7 +271,7 @@ class TestUnlistedAllList(TestCase):
self.new_file('Deleted', addon_status=amo.STATUS_PUBLIC, self.new_file('Deleted', addon_status=amo.STATUS_PUBLIC,
file_status=amo.STATUS_PUBLIC)['addon'].delete() file_status=amo.STATUS_PUBLIC)['addon'].delete()
assert sorted(q.addon_name for q in self.Queue.objects.all()) == ( assert sorted(q.addon_name for q in self.Queue.objects.all()) == (
['Deleted', 'Lite', 'Nominated', 'Public', 'Unreviewed']) ['Deleted', 'Nominated', 'Public'])
def test_authors(self): def test_authors(self):
addon = self.new_file()['addon'] addon = self.new_file()['addon']
@ -341,7 +287,7 @@ class TestUnlistedAllList(TestCase):
today = datetime.today().date() today = datetime.today().date()
self.new_file(name='addon123', version='1.0') self.new_file(name='addon123', version='1.0')
v2 = self.new_file(name='addon123', version='2.0')['version'] v2 = self.new_file(name='addon123', version='2.0')['version']
log = amo.log(amo.LOG.PRELIMINARY_VERSION, v2, v2.addon, log = amo.log(amo.LOG.APPROVE_VERSION, v2, v2.addon,
user=UserProfile.objects.get(pk=999)) user=UserProfile.objects.get(pk=999))
self.new_file(name='addon123', version='3.0') self.new_file(name='addon123', version='3.0')
row = self.Queue.objects.all()[0] row = self.Queue.objects.all()[0]
@ -357,7 +303,7 @@ class TestUnlistedAllList(TestCase):
assert row.review_version_num is None assert row.review_version_num is None
ver = self.new_file(name='addon456', version='2.0')['version'] ver = self.new_file(name='addon456', version='2.0')['version']
amo.log(amo.LOG.PRELIMINARY_VERSION, ver, ver.addon, amo.log(amo.LOG.APPROVE_VERSION, ver, ver.addon,
user=UserProfile.objects.get(pk=999)) user=UserProfile.objects.get(pk=999))
row = self.Queue.objects.all()[0] row = self.Queue.objects.all()[0]
assert row.review_version_num == '2.0' assert row.review_version_num == '2.0'
@ -371,7 +317,7 @@ class TestUnlistedAllList(TestCase):
def test_no_automatic_reviews(self): def test_no_automatic_reviews(self):
ver = self.new_file(name='addon789', version='1.0')['version'] ver = self.new_file(name='addon789', version='1.0')['version']
amo.log(amo.LOG.PRELIMINARY_VERSION, ver, ver.addon, amo.log(amo.LOG.APPROVE_VERSION, ver, ver.addon,
user=UserProfile.objects.get(pk=settings.TASK_USER_ID)) user=UserProfile.objects.get(pk=settings.TASK_USER_ID))
row = self.Queue.objects.all()[0] row = self.Queue.objects.all()[0]
assert row.review_version_num is None assert row.review_version_num is None
@ -491,14 +437,11 @@ class TestReviewerScore(TestCase):
} }
statuses = { statuses = {
amo.STATUS_NULL: None, amo.STATUS_NULL: None,
amo.STATUS_UNREVIEWED: 'PRELIM',
amo.STATUS_PENDING: None, amo.STATUS_PENDING: None,
amo.STATUS_NOMINATED: 'FULL', amo.STATUS_NOMINATED: 'FULL',
amo.STATUS_PUBLIC: 'UPDATE', amo.STATUS_PUBLIC: 'UPDATE',
amo.STATUS_DISABLED: None, amo.STATUS_DISABLED: None,
amo.STATUS_BETA: None, amo.STATUS_BETA: None,
amo.STATUS_LITE: 'PRELIM',
amo.STATUS_LITE_AND_NOMINATED: 'FULL',
amo.STATUS_DELETED: None, amo.STATUS_DELETED: None,
amo.STATUS_REJECTED: None, amo.STATUS_REJECTED: None,
amo.STATUS_REVIEW_PENDING: None, amo.STATUS_REVIEW_PENDING: None,
@ -523,16 +466,16 @@ class TestReviewerScore(TestCase):
user2 = UserProfile.objects.get(email='admin@mozilla.com') user2 = UserProfile.objects.get(email='admin@mozilla.com')
bonus_days = 2 bonus_days = 2
days = amo.REVIEWED_OVERDUE_LIMIT + bonus_days days = amo.REVIEWED_OVERDUE_LIMIT + bonus_days
addon_objects = create_addon_file( bonus_addon = create_addon_file(
u'AwardBonus', u'AwardBonus',
u'1.0', u'1.0',
amo.STATUS_NOMINATED, amo.STATUS_NOMINATED,
amo.STATUS_UNREVIEWED, amo.STATUS_UNREVIEWED,
nomination=(datetime.now() - timedelta(days=days)) nomination=(datetime.now() - timedelta(days=days, minutes=5))
) )['addon']
self._give_points(user2, addon_objects['addon'], 1) self._give_points(user2, bonus_addon, amo.STATUS_NOMINATED)
score = ReviewerScore.objects.get(user=user2) score = ReviewerScore.objects.get(user=user2)
expected = (amo.REVIEWED_SCORES[amo.REVIEWED_ADDON_PRELIM] + expected = (amo.REVIEWED_SCORES[amo.REVIEWED_ADDON_FULL] +
(amo.REVIEWED_OVERDUE_BONUS * bonus_days)) (amo.REVIEWED_OVERDUE_BONUS * bonus_days))
assert score.score == expected assert score.score == expected
@ -547,11 +490,11 @@ class TestReviewerScore(TestCase):
def test_get_total(self): def test_get_total(self):
user2 = UserProfile.objects.get(email='admin@mozilla.com') user2 = UserProfile.objects.get(email='admin@mozilla.com')
self._give_points() self._give_points()
self._give_points(status=amo.STATUS_LITE) self._give_points(status=amo.STATUS_PUBLIC)
self._give_points(user=user2, status=amo.STATUS_NOMINATED) self._give_points(user=user2, status=amo.STATUS_NOMINATED)
assert ReviewerScore.get_total(self.user) == ( assert ReviewerScore.get_total(self.user) == (
amo.REVIEWED_SCORES[amo.REVIEWED_ADDON_FULL] + amo.REVIEWED_SCORES[amo.REVIEWED_ADDON_FULL] +
amo.REVIEWED_SCORES[amo.REVIEWED_ADDON_PRELIM]) amo.REVIEWED_SCORES[amo.REVIEWED_ADDON_UPDATE])
assert ReviewerScore.get_total(user2) == ( assert ReviewerScore.get_total(user2) == (
amo.REVIEWED_SCORES[amo.REVIEWED_ADDON_FULL]) amo.REVIEWED_SCORES[amo.REVIEWED_ADDON_FULL])
@ -559,19 +502,19 @@ class TestReviewerScore(TestCase):
user2 = UserProfile.objects.get(email='admin@mozilla.com') user2 = UserProfile.objects.get(email='admin@mozilla.com')
self._give_points() self._give_points()
time.sleep(1) # Wait 1 sec so ordering by created is checked. time.sleep(1) # Wait 1 sec so ordering by created is checked.
self._give_points(status=amo.STATUS_LITE) self._give_points(status=amo.STATUS_PUBLIC)
self._give_points(user=user2) self._give_points(user=user2)
scores = ReviewerScore.get_recent(self.user) scores = ReviewerScore.get_recent(self.user)
assert len(scores) == 2 assert len(scores) == 2
assert scores[0].score == ( assert scores[0].score == (
amo.REVIEWED_SCORES[amo.REVIEWED_ADDON_PRELIM]) amo.REVIEWED_SCORES[amo.REVIEWED_ADDON_UPDATE])
assert scores[1].score == ( assert scores[1].score == (
amo.REVIEWED_SCORES[amo.REVIEWED_ADDON_FULL]) amo.REVIEWED_SCORES[amo.REVIEWED_ADDON_FULL])
def test_get_leaderboards(self): def test_get_leaderboards(self):
user2 = UserProfile.objects.get(email='regular@mozilla.com') user2 = UserProfile.objects.get(email='regular@mozilla.com')
self._give_points() self._give_points()
self._give_points(status=amo.STATUS_LITE) self._give_points(status=amo.STATUS_PUBLIC)
self._give_points(user=user2, status=amo.STATUS_NOMINATED) self._give_points(user=user2, status=amo.STATUS_NOMINATED)
leaders = ReviewerScore.get_leaderboards(self.user) leaders = ReviewerScore.get_leaderboards(self.user)
assert leaders['user_rank'] == 1 assert leaders['user_rank'] == 1
@ -580,7 +523,7 @@ class TestReviewerScore(TestCase):
assert leaders['leader_top'][0]['user_id'] == self.user.id assert leaders['leader_top'][0]['user_id'] == self.user.id
assert leaders['leader_top'][0]['total'] == ( assert leaders['leader_top'][0]['total'] == (
amo.REVIEWED_SCORES[amo.REVIEWED_ADDON_FULL] + amo.REVIEWED_SCORES[amo.REVIEWED_ADDON_FULL] +
amo.REVIEWED_SCORES[amo.REVIEWED_ADDON_PRELIM]) amo.REVIEWED_SCORES[amo.REVIEWED_ADDON_UPDATE])
assert leaders['leader_top'][1]['rank'] == 2 assert leaders['leader_top'][1]['rank'] == 2
assert leaders['leader_top'][1]['user_id'] == user2.id assert leaders['leader_top'][1]['user_id'] == user2.id
assert leaders['leader_top'][1]['total'] == ( assert leaders['leader_top'][1]['total'] == (
@ -596,7 +539,7 @@ class TestReviewerScore(TestCase):
def test_no_admins_or_staff_in_leaderboards(self): def test_no_admins_or_staff_in_leaderboards(self):
user2 = UserProfile.objects.get(email='admin@mozilla.com') user2 = UserProfile.objects.get(email='admin@mozilla.com')
self._give_points() self._give_points()
self._give_points(status=amo.STATUS_LITE) self._give_points(status=amo.STATUS_PUBLIC)
self._give_points(user=user2, status=amo.STATUS_NOMINATED) self._give_points(user=user2, status=amo.STATUS_NOMINATED)
leaders = ReviewerScore.get_leaderboards(self.user) leaders = ReviewerScore.get_leaderboards(self.user)
assert leaders['user_rank'] == 1 assert leaders['user_rank'] == 1
@ -626,12 +569,12 @@ class TestReviewerScore(TestCase):
user2 = UserProfile.objects.get(email='regular@mozilla.com') user2 = UserProfile.objects.get(email='regular@mozilla.com')
amo.REVIEWED_LEVELS[0]['points'] = 180 amo.REVIEWED_LEVELS[0]['points'] = 180
self._give_points() self._give_points()
self._give_points(status=amo.STATUS_LITE) self._give_points(status=amo.STATUS_PUBLIC)
self._give_points(user=user2, status=amo.STATUS_NOMINATED) self._give_points(user=user2, status=amo.STATUS_NOMINATED)
users = ReviewerScore.all_users_by_score() users = ReviewerScore.all_users_by_score()
assert len(users) == 2 assert len(users) == 2
# First user. # First user.
assert users[0]['total'] == 180 assert users[0]['total'] == 200
assert users[0]['user_id'] == self.user.id assert users[0]['user_id'] == self.user.id
assert users[0]['level'] == amo.REVIEWED_LEVELS[0]['name'] assert users[0]['level'] == amo.REVIEWED_LEVELS[0]['name']
# Second user. # Second user.

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

@ -48,60 +48,15 @@ def addon_with_files(db):
('process_sandbox', amo.STATUS_NOMINATED, amo.STATUS_UNREVIEWED, ('process_sandbox', amo.STATUS_NOMINATED, amo.STATUS_UNREVIEWED,
helpers.ReviewAddon, 'nominated', amo.STATUS_NULL, helpers.ReviewAddon, 'nominated', amo.STATUS_NULL,
amo.STATUS_DISABLED), amo.STATUS_DISABLED),
# scenario2: should succeed, files approved.
('process_preliminary', amo.STATUS_NOMINATED, amo.STATUS_UNREVIEWED,
helpers.ReviewAddon, 'nominated', amo.STATUS_LITE, amo.STATUS_LITE),
# New addon request prelim.
# scenario3: should fail, no change.
('process_public', amo.STATUS_UNREVIEWED, amo.STATUS_UNREVIEWED,
helpers.ReviewAddon, 'preliminary', amo.STATUS_UNREVIEWED,
amo.STATUS_UNREVIEWED),
# scenario4: Should succeed, files rejected.
('process_sandbox', amo.STATUS_UNREVIEWED, amo.STATUS_UNREVIEWED,
helpers.ReviewAddon, 'preliminary', amo.STATUS_NULL,
amo.STATUS_DISABLED),
# scenario5: should succeed, files approved.
('process_preliminary', amo.STATUS_UNREVIEWED, amo.STATUS_UNREVIEWED,
helpers.ReviewAddon, 'preliminary', amo.STATUS_LITE, amo.STATUS_LITE),
# Prelim addon request full.
# scenario6: should succeed, files approved.
('process_public', amo.STATUS_LITE_AND_NOMINATED, amo.STATUS_LITE,
helpers.ReviewAddon, 'nominated', amo.STATUS_PUBLIC,
amo.STATUS_PUBLIC),
# scenario7: should succeed, files rejected.
('process_sandbox', amo.STATUS_LITE_AND_NOMINATED, amo.STATUS_LITE,
helpers.ReviewAddon, 'nominated', amo.STATUS_NULL,
amo.STATUS_LITE),
# scenario8: Should succeed, files approved.
('process_preliminary', amo.STATUS_LITE_AND_NOMINATED, amo.STATUS_LITE,
helpers.ReviewAddon, 'nominated', amo.STATUS_LITE, amo.STATUS_LITE),
# Full addon with a new file. # Full addon with a new file.
# scenario9: should succeed, files approved. # scenario2: should succeed, files approved.
('process_public', amo.STATUS_PUBLIC, amo.STATUS_UNREVIEWED, ('process_public', amo.STATUS_PUBLIC, amo.STATUS_UNREVIEWED,
helpers.ReviewFiles, 'pending', amo.STATUS_PUBLIC, amo.STATUS_PUBLIC), helpers.ReviewFiles, 'pending', amo.STATUS_PUBLIC, amo.STATUS_PUBLIC),
# scenario10: should succeed, files rejected. # scenario3: should succeed, files rejected.
('process_sandbox', amo.STATUS_PUBLIC, amo.STATUS_UNREVIEWED, ('process_sandbox', amo.STATUS_PUBLIC, amo.STATUS_UNREVIEWED,
helpers.ReviewFiles, 'pending', amo.STATUS_NOMINATED, helpers.ReviewFiles, 'pending', amo.STATUS_NOMINATED,
amo.STATUS_DISABLED), amo.STATUS_DISABLED),
# scenario11: should succeed, files approved.
('process_preliminary', amo.STATUS_PUBLIC, amo.STATUS_UNREVIEWED,
helpers.ReviewFiles, 'pending', amo.STATUS_LITE, amo.STATUS_LITE),
# Prelim addon with a new file.
# scenario12: should fail, no change.
('process_public', amo.STATUS_LITE, amo.STATUS_UNREVIEWED,
helpers.ReviewFiles, 'preliminary', amo.STATUS_LITE,
amo.STATUS_UNREVIEWED),
# scenario13: should succeed, files rejected.
('process_sandbox', amo.STATUS_LITE, amo.STATUS_UNREVIEWED,
helpers.ReviewFiles, 'preliminary', amo.STATUS_LITE,
amo.STATUS_DISABLED),
# scenario14: should succeed, files approved.
('process_preliminary', amo.STATUS_LITE, amo.STATUS_UNREVIEWED,
helpers.ReviewFiles, 'preliminary', amo.STATUS_LITE, amo.STATUS_LITE),
]) ])
def test_review_scenario(mock_request, addon_with_files, review_action, def test_review_scenario(mock_request, addon_with_files, review_action,
addon_status, file_status, review_class, review_type, addon_status, file_status, review_class, review_type,
@ -118,7 +73,7 @@ def test_review_scenario(mock_request, addon_with_files, review_action,
helper.get_review_type(mock_request, addon, version) helper.get_review_type(mock_request, addon, version)
assert helper.review_type == review_type assert helper.review_type == review_type
helper.set_data({'comments': 'testing review scenarios'}) helper.set_data({'comments': 'testing review scenarios'})
# Run the action (process_public, process_sandbox, process_preliminary). # Run the action (process_public, process_sandbox).
try: try:
getattr(helper.handler, review_action)() getattr(helper.handler, review_action)()
except AssertionError: except AssertionError:

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

@ -540,12 +540,10 @@ class TestHome(EditorTest):
listed_queues_links = [ listed_queues_links = [
reverse('editors.queue_nominated'), reverse('editors.queue_nominated'),
reverse('editors.queue_pending'), reverse('editors.queue_pending'),
reverse('editors.queue_prelim'),
reverse('editors.queue_moderated')] reverse('editors.queue_moderated')]
unlisted_queues_links = [ unlisted_queues_links = [
reverse('editors.unlisted_queue_nominated'), reverse('editors.unlisted_queue_nominated'),
reverse('editors.unlisted_queue_pending'), reverse('editors.unlisted_queue_pending'),
reverse('editors.unlisted_queue_prelim'),
reverse('editors.unlisted_queue_all')] reverse('editors.unlisted_queue_all')]
# Only listed queues for editors. # Only listed queues for editors.
@ -634,23 +632,13 @@ class QueueTest(EditorTest):
}), }),
('Nominated Two', { ('Nominated Two', {
'version_str': '0.1', 'version_str': '0.1',
'addon_status': amo.STATUS_LITE_AND_NOMINATED, 'addon_status': amo.STATUS_NOMINATED,
'file_status': amo.STATUS_LITE,
}),
('Prelim One', {
'version_str': '0.1',
'addon_status': amo.STATUS_LITE,
'file_status': amo.STATUS_UNREVIEWED,
}),
('Prelim Two', {
'version_str': '0.1',
'addon_status': amo.STATUS_UNREVIEWED,
'file_status': amo.STATUS_UNREVIEWED, 'file_status': amo.STATUS_UNREVIEWED,
}), }),
('Public', { ('Public', {
'version_str': '0.1', 'version_str': '0.1',
'addon_status': amo.STATUS_PUBLIC, 'addon_status': amo.STATUS_PUBLIC,
'file_status': amo.STATUS_LITE, 'file_status': amo.STATUS_PUBLIC,
}), }),
]) ])
results = SortedDict() results = SortedDict()
@ -819,7 +807,7 @@ class TestQueueBasics(QueueTest):
doc = pq(r.content) doc = pq(r.content)
assert doc('#navbar li.top ul').eq(0).text() == ( assert doc('#navbar li.top ul').eq(0).text() == (
'Full Reviews (2) Pending Updates (2) ' 'Full Reviews (2) Pending Updates (2) '
'Preliminary Reviews (2) Moderated Reviews (0)') 'Moderated Reviews (0)')
def test_legacy_queue_sort(self): def test_legacy_queue_sort(self):
sorts = ( sorts = (
@ -846,13 +834,6 @@ class TestQueueBasics(QueueTest):
for data in self.get_review_data(): for data in self.get_review_data():
self.check_bar(addon, eq=1, data=data, reset_status=True) self.check_bar(addon, eq=1, data=data, reset_status=True)
def test_prelim_bar(self):
self.generate_files()
addon = self.addons['Prelim One']
for data in self.get_review_data():
self.check_bar(addon, eq=2, data=data)
def check_bar(self, addon, eq, data, reset_status=False): def check_bar(self, addon, eq, data, reset_status=False):
# `eq` is the table number (0, 1 or 2). # `eq` is the table number (0, 1 or 2).
def style(w): def style(w):
@ -985,8 +966,7 @@ class TestUnlistedQueueBasics(TestQueueBasics):
assert r.status_code == 200 assert r.status_code == 200
doc = pq(r.content) doc = pq(r.content)
assert doc('#navbar li.top ul').eq(1).text() == ( assert doc('#navbar li.top ul').eq(1).text() == (
'Full Reviews (2) Pending Updates (2) Preliminary Reviews (2) ' 'Full Reviews (2) Pending Updates (2) All Add-ons (5)')
'All Add-ons (7)')
def test_listed_unlisted_queues(self): def test_listed_unlisted_queues(self):
# Make sure the listed addons are displayed in the listed queue, and # Make sure the listed addons are displayed in the listed queue, and
@ -1092,28 +1072,6 @@ class TestNominatedQueue(QueueTest):
self._test_get_queue() self._test_get_queue()
class TestPreliminaryQueue(QueueTest):
def setUp(self):
super(TestPreliminaryQueue, self).setUp()
# These should be the only ones present.
self.expected_addons = self.get_expected_addons_by_names(
['Prelim One', 'Prelim Two'])
self.url = reverse('editors.queue_prelim')
def test_results(self):
self._test_results()
def test_breadcrumbs(self):
self._test_breadcrumbs([('Preliminary Reviews', None)])
def test_queue_count(self):
self._test_queue_count(2, 'Preliminary Reviews', 2)
def test_get_queue(self):
self._test_get_queue()
class TestModeratedQueue(QueueTest): class TestModeratedQueue(QueueTest):
fixtures = ['base/users', 'reviews/dev-reply'] fixtures = ['base/users', 'reviews/dev-reply']
@ -1246,7 +1204,7 @@ class TestModeratedQueue(QueueTest):
note_key=amo.REVIEWED_ADDON_REVIEW).count() == 1 note_key=amo.REVIEWED_ADDON_REVIEW).count() == 1
def test_queue_count(self): def test_queue_count(self):
self._test_queue_count(3, 'Moderated Review', 1) self._test_queue_count(2, 'Moderated Review', 1)
def test_breadcrumbs(self): def test_breadcrumbs(self):
self._test_breadcrumbs([('Moderated Reviews', None)]) self._test_breadcrumbs([('Moderated Reviews', None)])
@ -1314,22 +1272,6 @@ class TestUnlistedNominatedQueue(TestNominatedQueue):
self._test_queue_count(0, 'Unlisted Full Reviews', 2) self._test_queue_count(0, 'Unlisted Full Reviews', 2)
class TestUnlistedPreliminaryQueue(TestPreliminaryQueue):
listed = False
def setUp(self):
super(TestUnlistedPreliminaryQueue, self).setUp()
self.url = reverse('editors.unlisted_queue_prelim')
# Don't need to call get_expected_addons_by_name() again because
# we already called it in setUp() of the parent class
def test_breadcrumbs(self):
self._test_breadcrumbs([('Unlisted Preliminary Reviews', None)])
def test_queue_count(self):
self._test_queue_count(2, 'Unlisted Preliminary Reviews', 2)
class TestUnlistedAllList(QueueTest): class TestUnlistedAllList(QueueTest):
listed = False listed = False
@ -1339,7 +1281,7 @@ class TestUnlistedAllList(QueueTest):
# We should have all add-ons. # We should have all add-ons.
self.expected_addons = self.get_expected_addons_by_names( self.expected_addons = self.get_expected_addons_by_names(
['Pending One', 'Pending Two', 'Nominated One', 'Nominated Two', ['Pending One', 'Pending Two', 'Nominated One', 'Nominated Two',
'Prelim One', 'Prelim Two', 'Public']) 'Public'])
# Need to set unique nomination times or we get a psuedo-random order. # Need to set unique nomination times or we get a psuedo-random order.
for idx, addon in enumerate(self.expected_addons): for idx, addon in enumerate(self.expected_addons):
addon.latest_version.update( addon.latest_version.update(
@ -1349,14 +1291,14 @@ class TestUnlistedAllList(QueueTest):
self._test_breadcrumbs([('All Unlisted Add-ons', None)]) self._test_breadcrumbs([('All Unlisted Add-ons', None)])
def test_queue_count(self): def test_queue_count(self):
assert Addon.with_unlisted.all().count() == 7 assert Addon.with_unlisted.all().count() == 5
self._test_queue_count(3, 'All Unlisted Add-ons', 7) self._test_queue_count(2, 'All Unlisted Add-ons', 5)
def test_results(self): def test_results(self):
self._test_results() self._test_results()
def test_review_notes_json(self): def test_review_notes_json(self):
log = amo.log(amo.LOG.PRELIMINARY_VERSION, log = amo.log(amo.LOG.APPROVE_VERSION,
self.expected_addons[0].latest_version, self.expected_addons[0].latest_version,
self.expected_addons[0], self.expected_addons[0],
user=UserProfile.objects.get(pk=999), user=UserProfile.objects.get(pk=999),
@ -1879,11 +1821,11 @@ class TestQueueSearchVersionSpecific(SearchTest):
def setUp(self): def setUp(self):
super(TestQueueSearchVersionSpecific, self).setUp() super(TestQueueSearchVersionSpecific, self).setUp()
self.url = reverse('editors.queue_prelim') self.url = reverse('editors.queue_nominated')
create_addon_file('Not Admin Reviewed', '0.1', create_addon_file('Not Admin Reviewed', '0.1',
amo.STATUS_LITE, amo.STATUS_UNREVIEWED) amo.STATUS_NOMINATED, amo.STATUS_UNREVIEWED)
create_addon_file('Justin Bieber Theme', '0.1', create_addon_file('Justin Bieber Theme', '0.1',
amo.STATUS_LITE, amo.STATUS_UNREVIEWED, amo.STATUS_NOMINATED, amo.STATUS_UNREVIEWED,
addon_type=amo.ADDON_THEME) addon_type=amo.ADDON_THEME)
self.bieber = Version.objects.filter( self.bieber = Version.objects.filter(
addon__name__localized_string='Justin Bieber Theme') addon__name__localized_string='Justin Bieber Theme')
@ -2104,7 +2046,7 @@ class TestReview(ReviewBase):
for idx in xrange(comments.length): for idx in xrange(comments.length):
td = comments.eq(idx) td = comments.eq(idx)
assert td.find('.history-comment').text() == 'something' assert td.find('.history-comment').text() == 'something'
assert td.find('th').text() == 'Preliminarily approved' assert td.find('th').text() == 'Approved'
assert td.find('td a').text() == self.editor.display_name assert td.find('td a').text() == self.editor.display_name
def generate_deleted_versions(self): def generate_deleted_versions(self):
@ -2114,7 +2056,7 @@ class TestReview(ReviewBase):
versions = ({'version': '0.1', 'action': 'comment', versions = ({'version': '0.1', 'action': 'comment',
'comments': 'millenium hand and shrimp'}, 'comments': 'millenium hand and shrimp'},
{'version': '0.1', 'action': 'prelim', {'version': '0.1', 'action': 'public',
'comments': 'buggrit'}, 'comments': 'buggrit'},
{'version': '0.2', 'action': 'comment', {'version': '0.2', 'action': 'comment',
'comments': 'I told em'}, 'comments': 'I told em'},
@ -2199,7 +2141,7 @@ class TestReview(ReviewBase):
def test_item_history_header(self): def test_item_history_header(self):
doc = pq(self.client.get(self.url).content) doc = pq(self.client.get(self.url).content)
assert ('Preliminarily Reviewed' in assert ('Reviewed' in
doc('#review-files .listing-header .light').text()) doc('#review-files .listing-header .light').text())
def test_item_history_comment(self): def test_item_history_comment(self):
@ -2331,16 +2273,8 @@ class TestReview(ReviewBase):
assert Addon.objects.get(pk=self.addon.pk).admin_review assert Addon.objects.get(pk=self.addon.pk).admin_review
def test_no_public(self): def test_no_public(self):
s = amo.STATUS_PUBLIC has_public = self.version.files.filter(
status=amo.STATUS_PUBLIC).exists()
has_public = self.version.files.filter(status=s).exists()
assert not has_public
for version_file in self.version.files.all():
version_file.status = amo.STATUS_PUBLIC
version_file.save()
has_public = self.version.files.filter(status=s).exists()
assert has_public assert has_public
response = self.client.get(self.url) response = self.client.get(self.url)
@ -2427,7 +2361,7 @@ class TestReview(ReviewBase):
@patch('olympia.editors.helpers.sign_file') @patch('olympia.editors.helpers.sign_file')
def review_version(self, version, url, mock_sign): def review_version(self, version, url, mock_sign):
version.files.all()[0].update(status=amo.STATUS_UNREVIEWED) version.files.all()[0].update(status=amo.STATUS_UNREVIEWED)
data = dict(action='prelim', operating_systems='win', data = dict(action='public', operating_systems='win',
applications='something', comments='something') applications='something', comments='something')
self.client.post(url, data) self.client.post(url, data)
@ -2468,16 +2402,12 @@ class TestReview(ReviewBase):
self.assertContains(r, 'View Privacy Policy') self.assertContains(r, 'View Privacy Policy')
def test_breadcrumbs_all(self): def test_breadcrumbs_all(self):
queues = {'Full Reviews': [amo.STATUS_NOMINATED, queues = {'Full Reviews': amo.STATUS_NOMINATED,
amo.STATUS_LITE_AND_NOMINATED], 'Pending Updates': amo.STATUS_PUBLIC}
'Preliminary Reviews': [amo.STATUS_UNREVIEWED, for text, queue_id in queues.items():
amo.STATUS_LITE], self.addon.update(status=queue_id)
'Pending Updates': [amo.STATUS_PENDING, amo.STATUS_PUBLIC]} doc = pq(self.client.get(self.url).content)
for text, queue_ids in queues.items(): assert doc('#breadcrumbs li').eq(1).text() == text
for qid in queue_ids:
self.addon.update(status=qid)
doc = pq(self.client.get(self.url).content)
assert doc('#breadcrumbs li').eq(1).text() == text
def test_viewing(self): def test_viewing(self):
url = reverse('editors.review_viewing') url = reverse('editors.review_viewing')
@ -2739,61 +2669,6 @@ class TestReview(ReviewBase):
assert not validate.called assert not validate.called
class TestReviewPreliminary(ReviewBase):
def prelim_dict(self):
return self.get_dict(action='prelim')
def test_prelim_comments_requested(self):
response = self.client.post(self.url, {'action': 'prelim'})
assert response.context['form'].errors['comments'][0] == (
'This field is required.')
@patch('olympia.editors.helpers.sign_file')
def test_prelim_from_lite(self, mock_sign):
self.addon.update(status=amo.STATUS_LITE)
self.version.files.all()[0].update(status=amo.STATUS_UNREVIEWED)
response = self.client.post(self.url, self.prelim_dict())
assert response.status_code == 302
assert self.get_addon().status == amo.STATUS_LITE
assert mock_sign.called
def test_prelim_from_lite_required(self):
self.version.files.update(status=amo.STATUS_UNREVIEWED)
self.addon.update(status=amo.STATUS_LITE)
response = self.client.post(self.url, {'action': 'prelim'})
assert response.context['form'].errors['comments'][0] == (
'This field is required.')
def test_prelim_from_lite_files(self):
self.version.files.update(status=amo.STATUS_UNREVIEWED)
self.addon.update(status=amo.STATUS_LITE)
self.client.post(self.url, self.prelim_dict())
assert self.get_addon().status == amo.STATUS_LITE
@patch('olympia.editors.helpers.sign_file')
def test_prelim_from_unreviewed(self, mock_sign):
self.version.files.update(status=amo.STATUS_UNREVIEWED)
self.addon.update(status=amo.STATUS_UNREVIEWED)
response = self.client.post(self.url, self.prelim_dict())
assert response.status_code == 302
assert self.get_addon().status == amo.STATUS_LITE
assert mock_sign.called
def test_prelim_multiple_files(self):
file_ = self.version.files.all()[0]
file_.pk = None
file_.status = amo.STATUS_DISABLED
file_.save()
self.addon.update(status=amo.STATUS_LITE)
data = self.prelim_dict()
self.client.post(self.url, data)
assert [amo.STATUS_DISABLED, amo.STATUS_LITE] == (
[f.status for f in self.version.files.all().order_by('status')])
class TestReviewPending(ReviewBase): class TestReviewPending(ReviewBase):
def setUp(self): def setUp(self):
@ -2809,7 +2684,7 @@ class TestReviewPending(ReviewBase):
def test_pending_to_public(self, mock_sign): def test_pending_to_public(self, mock_sign):
statuses = (self.version.files.values_list('status', flat=True) statuses = (self.version.files.values_list('status', flat=True)
.order_by('status')) .order_by('status'))
assert list(statuses) == [amo.STATUS_UNREVIEWED, amo.STATUS_LITE] assert list(statuses) == [amo.STATUS_UNREVIEWED, amo.STATUS_PUBLIC]
response = self.client.post(self.url, self.pending_dict()) response = self.client.post(self.url, self.pending_dict())
assert self.get_addon().status == amo.STATUS_PUBLIC assert self.get_addon().status == amo.STATUS_PUBLIC
@ -2817,7 +2692,7 @@ class TestReviewPending(ReviewBase):
statuses = (self.version.files.values_list('status', flat=True) statuses = (self.version.files.values_list('status', flat=True)
.order_by('status')) .order_by('status'))
assert list(statuses) == [amo.STATUS_PUBLIC, amo.STATUS_LITE] assert list(statuses) == [amo.STATUS_PUBLIC, amo.STATUS_PUBLIC]
assert mock_sign.called assert mock_sign.called
@ -2826,7 +2701,7 @@ class TestReviewPending(ReviewBase):
self.addon.update(is_listed=False) self.addon.update(is_listed=False)
statuses = (self.version.files.values_list('status', flat=True) statuses = (self.version.files.values_list('status', flat=True)
.order_by('status')) .order_by('status'))
assert list(statuses) == [amo.STATUS_UNREVIEWED, amo.STATUS_LITE] assert list(statuses) == [amo.STATUS_UNREVIEWED, amo.STATUS_PUBLIC]
self.login_as_admin() self.login_as_admin()
response = self.client.post(self.url, self.pending_dict()) response = self.client.post(self.url, self.pending_dict())
@ -2835,7 +2710,7 @@ class TestReviewPending(ReviewBase):
statuses = (self.version.files.values_list('status', flat=True) statuses = (self.version.files.values_list('status', flat=True)
.order_by('status')) .order_by('status'))
assert list(statuses) == [amo.STATUS_PUBLIC, amo.STATUS_LITE] assert list(statuses) == [amo.STATUS_PUBLIC, amo.STATUS_PUBLIC]
assert mock_sign.called assert mock_sign.called
@ -2948,29 +2823,16 @@ class TestStatusFile(ReviewBase):
r = self.client.get(self.url) r = self.client.get(self.url)
assert pq(r.content)('#review-files .file-info div').text() == expected assert pq(r.content)('#review-files .file-info div').text() == expected
def test_status_prelim(self):
self.get_file().update(status=amo.STATUS_UNREVIEWED)
for status in [amo.STATUS_UNREVIEWED, amo.STATUS_LITE]:
self.addon.update(status=status)
self.check_status('Pending Preliminary Review')
def test_status_full(self): def test_status_full(self):
self.get_file().update(status=amo.STATUS_UNREVIEWED) self.get_file().update(status=amo.STATUS_UNREVIEWED)
for status in [amo.STATUS_NOMINATED, amo.STATUS_PUBLIC]: for status in [amo.STATUS_NOMINATED, amo.STATUS_PUBLIC]:
self.addon.update(status=status) self.addon.update(status=status)
self.check_status('Pending Full Review') self.check_status('Awaiting Review')
def test_status_upgrade_to_full(self):
self.addon.update(status=amo.STATUS_LITE_AND_NOMINATED)
for status in [amo.STATUS_UNREVIEWED, amo.STATUS_LITE]:
self.get_file().update(status=status)
self.check_status('Pending Full Review')
def test_status_full_reviewed(self): def test_status_full_reviewed(self):
self.get_file().update(status=amo.STATUS_PUBLIC) self.get_file().update(status=amo.STATUS_PUBLIC)
for status in set(amo.UNDER_REVIEW_STATUSES + amo.LITE_STATUSES): self.addon.update(status=amo.STATUS_PUBLIC)
self.addon.update(status=status) self.check_status('Fully Reviewed')
self.check_status('Fully Reviewed')
def test_other(self): def test_other(self):
self.addon.update(status=amo.STATUS_BETA) self.addon.update(status=amo.STATUS_BETA)

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

@ -12,8 +12,6 @@ urlpatterns = (
name='editors.queue_nominated'), name='editors.queue_nominated'),
url(r'^queue/pending$', views.queue_pending, url(r'^queue/pending$', views.queue_pending,
name='editors.queue_pending'), name='editors.queue_pending'),
url(r'^queue/preliminary$', views.queue_prelim,
name='editors.queue_prelim'),
url(r'^queue/reviews$', views.queue_moderated, url(r'^queue/reviews$', views.queue_moderated,
name='editors.queue_moderated'), name='editors.queue_moderated'),
url(r'^queue/application_versions\.json$', views.application_versions_json, url(r'^queue/application_versions\.json$', views.application_versions_json,
@ -24,8 +22,6 @@ urlpatterns = (
name='editors.unlisted_queue_nominated'), name='editors.unlisted_queue_nominated'),
url(r'^unlisted_queue/pending$', views.unlisted_queue_pending, url(r'^unlisted_queue/pending$', views.unlisted_queue_pending,
name='editors.unlisted_queue_pending'), name='editors.unlisted_queue_pending'),
url(r'^unlisted_queue/preliminary$', views.unlisted_queue_prelim,
name='editors.unlisted_queue_prelim'),
url(r'^unlisted_queue/all$', views.unlisted_list, url(r'^unlisted_queue/all$', views.unlisted_list,
name='editors.unlisted_queue_all'), name='editors.unlisted_queue_all'),
url(r'^logs$', views.eventlog, name='editors.eventlog'), url(r'^logs$', views.eventlog, name='editors.eventlog'),

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

@ -27,15 +27,12 @@ from olympia.devhub.models import ActivityLog, AddonLog, CommentLog
from olympia.editors import forms from olympia.editors import forms
from olympia.editors.models import ( from olympia.editors.models import (
AddonCannedResponse, EditorSubscription, EventLog, PerformanceGraph, AddonCannedResponse, EditorSubscription, EventLog, PerformanceGraph,
ReviewerScore, ViewFullReviewQueue, ViewPendingQueue, ReviewerScore, ViewFullReviewQueue, ViewPendingQueue, ViewQueue,
ViewPreliminaryQueue, ViewQueue, ViewUnlistedAllList, ViewUnlistedAllList, ViewUnlistedFullReviewQueue, ViewUnlistedPendingQueue)
ViewUnlistedFullReviewQueue,
ViewUnlistedPendingQueue, ViewUnlistedPreliminaryQueue)
from olympia.editors.helpers import ( from olympia.editors.helpers import (
is_limited_reviewer, ReviewHelper, ViewFullReviewQueueTable, is_limited_reviewer, ReviewHelper, ViewFullReviewQueueTable,
ViewPendingQueueTable, ViewPreliminaryQueueTable, ViewUnlistedAllListTable, ViewPendingQueueTable, ViewUnlistedAllListTable,
ViewUnlistedFullReviewQueueTable, ViewUnlistedPendingQueueTable, ViewUnlistedFullReviewQueueTable, ViewUnlistedPendingQueueTable)
ViewUnlistedPreliminaryQueueTable)
from olympia.reviews.forms import ReviewFlagFormSet from olympia.reviews.forms import ReviewFlagFormSet
from olympia.reviews.models import Review, ReviewFlag from olympia.reviews.models import Review, ReviewFlag
from olympia.users.models import UserProfile from olympia.users.models import UserProfile
@ -203,7 +200,7 @@ def _editor_progress(unlisted=False, limited_reviewer=False):
"""Return the progress (number of add-ons still unreviewed for a given """Return the progress (number of add-ons still unreviewed for a given
period of time) and the percentage (out of all add-ons of that type).""" period of time) and the percentage (out of all add-ons of that type)."""
types = ['nominated', 'prelim', 'pending'] types = ['nominated', 'pending']
progress = {'new': queue_counts(types, days_max=4, unlisted=unlisted, progress = {'new': queue_counts(types, days_max=4, unlisted=unlisted,
admin_reviewer=True, admin_reviewer=True,
limited_reviewer=limited_reviewer), limited_reviewer=limited_reviewer),
@ -462,7 +459,6 @@ def queue_counts(type=None, unlisted=False, admin_reviewer=False,
counts = {'pending': construct_query(ViewPendingQueue, **kw), counts = {'pending': construct_query(ViewPendingQueue, **kw),
'nominated': construct_query(ViewFullReviewQueue, **kw), 'nominated': construct_query(ViewFullReviewQueue, **kw),
'prelim': construct_query(ViewPreliminaryQueue, **kw),
'moderated': ( 'moderated': (
Review.objects.filter(reviewflag__isnull=False, Review.objects.filter(reviewflag__isnull=False,
editorreview=1).count)} editorreview=1).count)}
@ -470,7 +466,6 @@ def queue_counts(type=None, unlisted=False, admin_reviewer=False,
counts = { counts = {
'pending': construct_query(ViewUnlistedPendingQueue, **kw), 'pending': construct_query(ViewUnlistedPendingQueue, **kw),
'nominated': construct_query(ViewUnlistedFullReviewQueue, **kw), 'nominated': construct_query(ViewUnlistedFullReviewQueue, **kw),
'prelim': construct_query(ViewUnlistedPreliminaryQueue, **kw),
'all': (ViewUnlistedAllList.objects if admin_reviewer 'all': (ViewUnlistedAllList.objects if admin_reviewer
else exclude_admin_only_addons( else exclude_admin_only_addons(
ViewUnlistedAllList.objects)).count} ViewUnlistedAllList.objects)).count}
@ -498,11 +493,6 @@ def queue_pending(request):
return _queue(request, ViewPendingQueueTable, 'pending') return _queue(request, ViewPendingQueueTable, 'pending')
@addons_reviewer_required
def queue_prelim(request):
return _queue(request, ViewPreliminaryQueueTable, 'prelim')
@addons_reviewer_required @addons_reviewer_required
def queue_moderated(request): def queue_moderated(request):
# In addition to other checks, this only show reviews for public and # In addition to other checks, this only show reviews for public and
@ -558,12 +548,6 @@ def unlisted_queue_pending(request):
unlisted=True) unlisted=True)
@unlisted_addons_reviewer_required
def unlisted_queue_prelim(request):
return _queue(request, ViewUnlistedPreliminaryQueueTable, 'prelim',
unlisted=True)
@addons_reviewer_required @addons_reviewer_required
@post_required @post_required
@json_view @json_view
@ -587,8 +571,7 @@ def review(request, addon):
form_helper = ReviewHelper(request=request, addon=addon, version=version) form_helper = ReviewHelper(request=request, addon=addon, version=version)
form = forms.ReviewForm(request.POST or None, helper=form_helper) form = forms.ReviewForm(request.POST or None, helper=form_helper)
queue_type = ('prelim' if form.helper.review_type == 'preliminary' queue_type = form.helper.review_type
else form.helper.review_type)
if addon.is_listed: if addon.is_listed:
redirect_url = reverse('editors.queue_%s' % queue_type) redirect_url = reverse('editors.queue_%s' % queue_type)
else: else:
@ -619,14 +602,11 @@ def review(request, addon):
canned = AddonCannedResponse.objects.all() canned = AddonCannedResponse.objects.all()
actions = form.helper.actions.items() actions = form.helper.actions.items()
statuses = [amo.STATUS_PUBLIC, amo.STATUS_LITE,
amo.STATUS_LITE_AND_NOMINATED]
try: try:
show_diff = version and ( show_diff = version and (
addon.versions.exclude(id=version.id).filter( addon.versions.exclude(id=version.id).filter(
files__isnull=False, created__lt=version.created, files__isnull=False, created__lt=version.created,
files__status__in=statuses).latest()) files__status=amo.STATUS_PUBLIC).latest())
except Version.DoesNotExist: except Version.DoesNotExist:
show_diff = None show_diff = None
@ -832,6 +812,7 @@ def reviewlog(request):
pager = amo.utils.paginate(request, approvals, 50) pager = amo.utils.paginate(request, approvals, 50)
ad = { ad = {
amo.LOG.APPROVE_VERSION.id: _('was approved'), amo.LOG.APPROVE_VERSION.id: _('was approved'),
# The log will still show preliminary, even after the migration.
amo.LOG.PRELIMINARY_VERSION.id: _('given preliminary review'), amo.LOG.PRELIMINARY_VERSION.id: _('given preliminary review'),
amo.LOG.REJECT_VERSION.id: _('rejected'), amo.LOG.REJECT_VERSION.id: _('rejected'),
amo.LOG.ESCALATE_VERSION.id: pgettext( amo.LOG.ESCALATE_VERSION.id: pgettext(

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

@ -278,20 +278,15 @@ class Version(OnChangeMixin, ModelBase):
def current_queue(self): def current_queue(self):
"""Return the current queue, or None if not in a queue.""" """Return the current queue, or None if not in a queue."""
from olympia.editors.models import ( from olympia.editors.models import (
ViewFullReviewQueue, ViewPendingQueue, ViewPreliminaryQueue, ViewFullReviewQueue, ViewPendingQueue,
ViewUnlistedFullReviewQueue, ViewUnlistedPendingQueue, ViewUnlistedFullReviewQueue, ViewUnlistedPendingQueue)
ViewUnlistedPreliminaryQueue)
if self.addon.status in [amo.STATUS_NOMINATED, if self.addon.status == amo.STATUS_NOMINATED:
amo.STATUS_LITE_AND_NOMINATED]:
return (ViewFullReviewQueue if self.addon.is_listed return (ViewFullReviewQueue if self.addon.is_listed
else ViewUnlistedFullReviewQueue) else ViewUnlistedFullReviewQueue)
elif self.addon.status == amo.STATUS_PUBLIC: elif self.addon.status == amo.STATUS_PUBLIC:
return (ViewPendingQueue if self.addon.is_listed return (ViewPendingQueue if self.addon.is_listed
else ViewUnlistedPendingQueue) else ViewUnlistedPendingQueue)
elif self.addon.status in [amo.STATUS_LITE, amo.STATUS_UNREVIEWED]:
return (ViewPreliminaryQueue if self.addon.is_listed
else ViewUnlistedPreliminaryQueue)
return None return None

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

@ -28,9 +28,8 @@ from olympia.addons.tests.test_views import TestMobile
from olympia.applications.models import AppVersion from olympia.applications.models import AppVersion
from olympia.devhub.models import ActivityLog from olympia.devhub.models import ActivityLog
from olympia.editors.models import ( from olympia.editors.models import (
ViewFullReviewQueue, ViewPendingQueue, ViewPreliminaryQueue, ViewFullReviewQueue, ViewPendingQueue,
ViewUnlistedFullReviewQueue, ViewUnlistedPendingQueue, ViewUnlistedFullReviewQueue, ViewUnlistedPendingQueue,)
ViewUnlistedPreliminaryQueue)
from olympia.files.models import File from olympia.files.models import File
from olympia.files.tests.test_models import UploadTest from olympia.files.tests.test_models import UploadTest
from olympia.users.models import UserProfile from olympia.users.models import UserProfile
@ -511,27 +510,22 @@ class TestVersion(TestCase):
def test_current_queue(self): def test_current_queue(self):
queue_to_status = { queue_to_status = {
ViewFullReviewQueue: [amo.STATUS_NOMINATED, ViewFullReviewQueue: amo.STATUS_NOMINATED,
amo.STATUS_LITE_AND_NOMINATED], ViewPendingQueue: amo.STATUS_PUBLIC
ViewPendingQueue: [amo.STATUS_PUBLIC], }
ViewPreliminaryQueue: [amo.STATUS_LITE, amo.STATUS_UNREVIEWED]}
unlisted_queue_to_status = { unlisted_queue_to_status = {
ViewUnlistedFullReviewQueue: [amo.STATUS_NOMINATED, ViewUnlistedFullReviewQueue: amo.STATUS_NOMINATED,
amo.STATUS_LITE_AND_NOMINATED], ViewUnlistedPendingQueue: amo.STATUS_PUBLIC,
ViewUnlistedPendingQueue: [amo.STATUS_PUBLIC], }
ViewUnlistedPreliminaryQueue: [amo.STATUS_LITE,
amo.STATUS_UNREVIEWED]}
for queue, statuses in queue_to_status.iteritems(): # Listed queues. for queue, status in queue_to_status.iteritems(): # Listed queues.
for status in statuses: self.version.addon.update(status=status)
self.version.addon.update(status=status) assert self.version.current_queue == queue
assert self.version.current_queue == queue
self.version.addon.update(is_listed=False) # Unlisted queues. self.version.addon.update(is_listed=False) # Unlisted queues.
for queue, statuses in unlisted_queue_to_status.iteritems(): for queue, status in unlisted_queue_to_status.iteritems():
for status in statuses: self.version.addon.update(status=status)
self.version.addon.update(status=status) assert self.version.current_queue == queue
assert self.version.current_queue == queue
def test_get_url_path(self): def test_get_url_path(self):
assert self.version.get_url_path() == ( assert self.version.get_url_path() == (

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

@ -272,10 +272,15 @@ ul.tabnav a:hover {
.editor-stats-title, .editor-stats-title,
.editor-stats-table { .editor-stats-table {
width: 33.3333%; width: 50%;
float: left; float: left;
} }
.editor-stats-title.three-col,
.editor-stats-table.three-col {
width: 33.333333%;
}
.editor-stats-title span, .editor-stats-title span,
.editor-stats-title a { .editor-stats-title a {
font-weight: bold; font-weight: bold;