Merge pull request #9677 from diox/replace-legacy-disco-pane-with-redirect

Remove as much legacy disco pane code as possible, redirecting to firefox "new" page
This commit is contained in:
Mathieu Pillard 2018-10-15 16:43:35 +02:00 коммит произвёл GitHub
Родитель c0315acf47 365aa1093b
Коммит ff7436750d
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
19 изменённых файлов: 48 добавлений и 1092 удалений

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

@ -2,17 +2,6 @@
{% if deps %}
<div class="notice dependencies">
<h3>{{ _('This add-on requires the following add-ons to work properly:') }}</h3>
{% if module_context == 'discovery' %}
<ul>
{% for dep in deps %}
<li>
<a href="{{ services_url('discovery.addons.detail', dep.slug, src='discovery-dependencies') }}">
<img src="{{ dep.icon }}" alt="">{{ dep.name }}</a>
</li>
{% endfor %}
</ul>
{% else %}
{{ deps|addon_grid(cols=3, src='dp-hc-dependencies', dl_src='dp-dl-dependencies') }}
{% endif %}
{{ deps|addon_grid(cols=3, src='dp-hc-dependencies', dl_src='dp-dl-dependencies') }}
</div>
{% endif %}

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

@ -1 +1 @@
{% for module in modules %}{{ module.render(module_context=module_context) }}{% endfor %}
{% for module in modules %}{{ module.render() }}{% endfor %}

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

@ -44,7 +44,7 @@ def flag(context, addon):
@library.global_function
@library.render_with('addons/impala/dependencies_note.html')
@jinja2.contextfunction
def dependencies_note(context, addon, module_context='impala'):
def dependencies_note(context, addon):
return new_context(**locals())

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

@ -63,14 +63,6 @@ class UtilsTest(TestCase):
assert d['learnmore'].endswith('/addon/a3615/?src=api'), (
'Add-on details URL does not end with "?src=api"')
def test_dict_disco(self):
"""Check for correct add-on detail URL for discovery pane."""
d = addon_to_dict(self.a, disco=True, src='discovery-personalrec')
u = '%s%s?src=discovery-personalrec' % (
settings.SERVICES_URL,
reverse('discovery.addons.detail', args=['a3615']))
assert d['learnmore'] == u
def test_sanitize(self):
"""Check that tags are stripped for summary and description."""
self.a.summary = self.a.description = 'i <3 <a href="">amo</a>!'

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

@ -83,7 +83,7 @@ class MonthlyPick(TemplatePromo):
monthly_pick = self.get_pick('')
except IndexError:
monthly_pick = None
return {'pick': monthly_pick, 'module_context': 'discovery'}
return {'pick': monthly_pick}
class CollectionPromo(PromoModule):
@ -129,13 +129,11 @@ class CollectionPromo(PromoModule):
normalize=True)
return cache_get_or_set(cache_key, fetch_and_filter_addons)
def render(self, module_context='discovery'):
if module_context == 'home':
self.platform = 'ALL'
self.version = None
def render(self):
self.platform = 'ALL'
self.version = None
context = {
'promo': self,
'module_context': module_context,
'descriptions': self.get_descriptions()
}
if self.collection:
@ -165,9 +163,6 @@ class TestPilot(TemplatePromo):
cls = 'promo promo-test-pilot'
template = 'legacy_discovery/modules/testpilot.html'
def context(self, **kwargs):
return {'module_context': 'discovery'}
class StarterPack(CollectionPromo):
slug = 'Starter Pack'

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

@ -1,37 +0,0 @@
{% extends "legacy_discovery/base.html" %}
{% block bodyclass %}detail{% endblock %}
{% block title %}{{ page_title(addon.name) }}{% endblock %}
{% if addon.type == amo.ADDON_PERSONA %}
{% set authors = users_list(addon.persona.listed_authors) or
addon.persona.display_username %}
{% else %}
{% set authors = users_list(addon.listed_authors) %}
{% endif %}
{% block content %}
<section id="main">
<header>
<p id="back"><a href="#" target="_self">{{ _('Back to Add-ons') }}</a></p>
<h1 class="addon">
<img class="icon" src="{{ addon.icon_url }}" alt="">
{{ addon.name }}
{% set version = addon.current_version %}
{% if not addon.is_persona() and version %}
<span class="version">{{ version.version }}</span>
{% endif %}
</h1>
<h2 class="author">
{{ _('by') }} {{ authors }}
</h2>
</header>
{% block main %}{% endblock %}
</section>
{% block secondary %}{% endblock %}
{% endblock %}
{% block js %}
{{ js('zamboni/discovery') }}
{% endblock %}

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

@ -1,82 +0,0 @@
{% extends "legacy_discovery/addons/base.html" %}
{% block main %}
{% if addon.type == amo.ADDON_PERSONA %}
{{ disco_persona_preview(addon.persona, linked=False, caption=True) }}
{% endif %}
<p{{ addon.summary|locale_html }}>{{ addon.summary|nl2br }}</p>
<ul id="install">
<li class="install-action">
{{ install_button(addon, show_warning=True, detailed=False) }}
</li>
<li><a href="{{ url('addons.detail', addon.slug, src='discovery-learnmore') }}"
id="learn-more" class="button">{{ _('Learn More') }}</a></li>
{% if addon.privacy_policy %}
<li class="privacy"><a href="{{ url('addons.privacy', addon.slug, src='discovery-learnmore') }}">
{{ _('View Privacy Policy') }}</a></li>
{% endif %}
{% if addon.eula %}
<li class="eula"><a href="{{ url('addons.eula', addon.slug, src='discovery-learnmore') }}">
{{ _('View End-User License Agreement') }}</a></li>
{% endif %}
</ul>
{{ dependencies_note(addon, 'discovery') }}
{% if addon.type != amo.ADDON_PERSONA %}
{% if addon.current_previews|length > 0 %}
<div id="images">
<ul class="nav-images">
<li class="nav-prev"><a href="#" class="prev">{{ _('Previous') }}</a></li>
<li class="nav-next"><a href="#" class="next">{{ _('Next') }}</a></li>
</ul>
<ul class="slider">
{%- for preview in addon.current_previews -%}
<li class="panel">
<a class="screenshot thumbnail" rel="jquery-lightbox"
href="{{ preview.image_url }}" title="{{ preview.caption }}">
<img src="{{ preview.thumbnail_url }}" alt="">
</a>
</li>
{%- endfor -%}
</ul>
</div>
{% endif %}
{% endif %}
<ul class="addon-info">
<li>
<h3>{{ _('Rating') }}</h3>
{{ reviews_link(addon) }}
</li>
<li>
<h3>{{ _('Active Users') }}</h3>
<p class="users">{{ addon.average_daily_users|numberfmt }}</p>
</li>
<li>
{% if addon.is_persona() %}
<h3>{{ _('Created') }}</h3>
<p><time datetime="{{ addon.created|isotime }}">{{
addon.created|date }}</time></p>
{% else %}
<h3>{{ _('Last Updated') }}</h3>
<p><time datetime="{{ addon.last_updated|isotime }}">{{
addon.last_updated|date }}</time></p>
{% endif %}
</li>
{% if addon.homepage %}
<li>
<h3>{{ _('Website') }}</h3>
<p><a href="{{ addon.homepage|external_url }}">{{ addon.homepage }}</a></p>
</li>
{% endif %}
</ul>
{% endblock %}
{% block secondary %}
<section id="addon-reviews">
{{ review_list_box(addon=addon, reviews=reviews) }}
</section>
{% endblock %}

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

@ -1,28 +0,0 @@
{% extends "legacy_discovery/addons/base.html" %}
{% block title %}
{# L10n: {0} is the name of the add-on #}
{{ page_title(_('End-User License Agreement for {0}')|format_html(addon.name)) }}
{% endblock %}
{% block bodyclass %}{{ super() }} eula{% endblock %}
{% block main %}
<h3>{{ _('End-User License Agreement') }}</h3>
<p>
{% trans addon_name=addon.name %}
{{ addon_name }} requires that you accept the following End-User License
Agreement before installation can proceed:
{% endtrans %}
</p>
<article id="eula">
<p>{{ addon.eula|nl2br }}</p>
</article>
<ul id="install" class="install-action">
<li>
{{ install_button(addon, version=version, show_warning=False) }}
</li>
<li><a href="{{ services_url('discovery.addons.detail', addon.slug, src=src) }}" class="button">
{{ _('Cancel Installation') }}</a></li>
</ul>
{% endblock %}

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

@ -1,25 +0,0 @@
<!DOCTYPE html>
<html lang="{{ LANG }}" dir="{{ DIR }}">
<head>
<meta charset="utf-8">
<meta name="robots" content="noindex">
<meta name="viewport" content="width=700">
<title>{% block title %}{{ _('Discover Add-ons') }}{% endblock %}</title>
{{ css('zamboni/discovery-pane') }}
<base target="_blank" rel="noreferrer" href="{{ settings.SITE_URL }}">
{% block extrahead %}{% endblock %}
</head>
<body class="html-{{ DIR }} {{ request.APP.short }} {% block bodyclass %}{% endblock %}"
data-app="{{ request.APP.short }}"
data-appname="{{ request.APP.pretty }}"
data-appid="{{ request.APP.id }}"
data-anonymous="{{ (not request.user.is_authenticated)|json }}"
data-readonly="{{ settings.READ_ONLY|json }}"
data-media-url="{{ MEDIA_URL }}"
data-static-url="{{ STATIC_URL }}"
{% block bodyattrs %}{% endblock %}>
{% block content %}{% endblock %}
<script src="{{ CDN_HOST }}{{ cache_buster(url('jsi18n')) }}"></script>
{% block js %}{% endblock %}
</body>
</html>

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

@ -1,34 +0,0 @@
{% macro addon_list(list, limit=5, sidebar=False, amo=None, src=None) %}
<ul>
{% if not src %}
{% set src = 'discovery-upandcoming' if sidebar else 'discovery-featured' %}
{% endif %}
{# These are JSON add-ons from the API, not Addon objects. #}
{% for addon in list[:limit] %}
{% if amo and addon.type == amo.ADDON_PERSONA %}
<li class="featured-themes">{{ disco_persona_preview(addon.persona, title=True, src=src) }}</li>
{% else %}
<li class="featured-addons" data-guid="{{ addon.guid }}">
<a href="{{ services_url('discovery.addons.detail', addon.id, src=src) }}"
target="_self" class="addon-title">
<img src="{{ addon.icon or addon.icon_url }}" width="32" height="32" alt="">
{% if sidebar %}
<span class="htruncate">{{ addon.name }}</span>
{% else %}
<h3 class="htruncate">{{ addon.name }}</h3>
<p class="desc vtruncate">{{ addon.summary }}</p>
{% endif %}
</a>
</li>
{% endif %}
{% endfor %}
</ul>
{% endmacro %}
{% macro persona_list(list, limit=5) %}
<ul class="persona-list">
{% for addon in list[:limit] %}
<li class="featured-themes">{{ disco_persona_preview(addon.persona, title=True, src='discovery-featured') }}</li>
{% endfor %}
</ul>
{% endmacro %}

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

@ -5,11 +5,7 @@
<hgroup>
{% if promo.linkify_title %}
<h2>
{% if module_context == 'discovery' %}
<a href="{{ collection.get_url_path()|urlparams(src='discovery-promo') }}">{{ promo.title|safe }}</a>
{% else %}
<a href="{{ collection.get_url_path()|urlparams(src='hp-dl-promo') }}">{{ promo.title|safe }}</a>
{% endif %}
<a href="{{ collection.get_url_path()|urlparams(src='hp-dl-promo') }}">{{ promo.title|safe }}</a>
</h2>
{% else %}
<h2>{{ promo.title|safe }}</h2>
@ -20,17 +16,12 @@
</hgroup>
<ul class="addons">
{% for addon in addons %}
<li data-guid="{{ addon.guid }}" data-ctx="{{ module_context }}"
<li data-guid="{{ addon.guid }}"
{% if addon.type == amo.ADDON_PERSONA %}class="persona-feature"{% endif %}>
{% if module_context == 'discovery' %}
<a href="{{ services_url('discovery.addons.detail', addon.slug,
src='discovery-promo') }}" target="_self">
{% else %}
<a href="{{ addon.get_url_path()|urlparams(src='hp-dl-promo') }}" target="_self">
{% endif %}
{% if addon.type == amo.ADDON_PERSONA %}
<h3 class="htruncate">{{ addon.name }}</h3>
{{ disco_persona_preview(addon.persona, linked=False) }}
{{ persona_preview(addon.persona, linked=False) }}
{% else %}
<img src="{{ addon.icon_url }}" width="32" height="32" alt="">
<h3 class="htruncate">{{ addon.name }}</h3>

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

@ -1,6 +1,5 @@
{%- if pick -%}
{% set is_disco = module_context == 'discovery' %}
{% set src = 'discovery-promo' if is_disco else 'hp-btn-promo' %}
{% set src = 'hp-btn-promo' %}
{% set addon = pick.addon %}
<li class="panel" data-addonguid="{{ addon.guid }}">
<div id="monthly" class="feature promo">
@ -9,15 +8,11 @@
</hgroup>
<div class="wrap">
<div>
{% if is_disco %}
{% set addon_url = services_url('discovery.addons.detail', addon.slug or addon.id, src=src) %}
{% else %}
{% set addon_url = addon.get_url_path()|urlparams(src=src) %}
{% endif %}
{% set addon_url = addon.get_url_path()|urlparams(src=src) %}
<div class="blurb">
<h3><a href="{{ addon_url }}" target="_self">{{ addon.name }}</a></h3>
<p>{{ pick.blurb }}</p>
{{ install_button(addon, impala=not is_disco) }}
{{ install_button(addon, impala=True) }}
<a href="{{ addon_url }}" target="_self" class="button details-link">
{{ _('Learn More') }}</a>
</div>

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

@ -1,9 +0,0 @@
{% from "legacy_discovery/macros.html" import addon_list with context %}
{% if featured_addons %}
{{ addon_list(featured_addons, limit=20) }}
{% endif %}
{% if up_and_coming %}
{{ addon_list(up_and_coming, limit=20, sidebar=True) }}
{% endif %}

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

@ -1,105 +0,0 @@
{% extends "legacy_discovery/base.html" %}
{% from "legacy_discovery/macros.html" import addon_list, persona_list with context %}
{% set app = request.APP.pretty %}
{% block bodyclass %}pane no-recs{% endblock %}
{% block bodyattrs %}
data-version="{{ version }}"
data-platform="{{ platform }}"
data-services-url="{{ settings.SERVICES_URL }}"
data-account-url="{{ services_url('discovery.pane.account') }}"
data-featured-url="{{ services_url('discovery.pane.more_addons', 'featured', version, platform, compat_mode) }}"
data-upandcoming-url="{{ services_url('discovery.pane.more_addons', 'up-and-coming', version, platform, compat_mode) }}"
{% endblock %}
{% block content %}
<header{% if user.is_authenticated %} class="auth"{% endif %}>
<section id="intro">
<h1>
<img src="{{ static('img/zamboni/discovery_pane/logo-addons.png') }}" width="87" height="82" alt="">
<span class="translate" data-trans="title">
{{ _('What are Add-ons?') }}
</span>
</h1>
<p>
<span class="translate" data-trans="intro">
{% trans %}
Add-ons are applications that let you personalize {{ app }} with
extra functionality or style. Try a time-saving sidebar, a weather
notifier, or a themed look to make {{ app }} your own.
{% endtrans %}
</span>
<a href="{{ url('home') }}" id="learn-more" class="button translate" data-trans="close">{{ _('Learn More') }}</a>
</p>
</section>
<section id="right-module"></section>
</header>
<section id="main">
<section id="promos" data-promo-url="{{ services_url('discovery.pane.promos', version, platform) }}">
<ul id="nav-features">
<li class="nav-prev"><a href="#" class="prev">{{ _('Previous') }}</a></li>
<li class="nav-next"><a href="#" class="next">{{ _('Next') }}</a></li>
</ul>
<ul class="slider"></ul>
</section>
{% if featured_addons %}
<section id="featured-addons">
<h2 class="translate" data-trans="featured">{{ _('Featured Add-ons') }}</h2>
<div class="addons">
{{ addon_list(featured_addons, limit=6) }}
</div>
</section>
{% endif %}
</section>
<section id="sub">
<div id="watch-video">
<a href="{{ url('home') }}" class="video button">{{ _('Learn More About Add-ons') }}</a>
</div>
{% if up_and_coming %}
<section class="featured featured-addons" id="up-and-coming">
<h2><a class="all" href="{{ url('browse.extensions')|urlparams(sort='hotness') }}">{{ _('See all') }}</a>
{{ _('Up & Coming') }}</h2>
{{ addon_list(up_and_coming, sidebar=True) }}
</section>
{% endif %}
{% if featured_personas %}
<section class="featured featured-themes" id="featured-themes">
<h2><a class="all" href="{{ url('browse.personas') }}">{{ _('See all') }}</a>
{{ _('Featured Themes') }}</h2>
{{ persona_list(featured_personas) }}
</section>
{% endif %}
<section id="more-ways">
<h2>{{ _('More ways to customize') }}</h2>
<ul>
<li id="more-addons">
<a href="{{ url('browse.extensions') }}">{{ _('Browse all add-ons') }}</a>
</li>
<li id="more-complete-themes">
<a href="{{ url('browse.themes') }}">{{ _('See all complete themes') }}</a>
</li>
</ul>
</section>
<section class="featured" id="promo-video-addons">
<h2>
<a id="video-close" class="all" href="#">{{ _('Close Video') }}</a>
<span class="translate" data-trans="addons">{{ _('Add-ons') }}</span>
</h2>
<div id="video-details">{{ _('While the video plays, the add-ons being mentioned will appear here.') }}</div>
{{ addon_list(promovideo, limit=50, sidebar=True, amo=amo, src='discovery-video') }}
</section>
</section>
{% endblock %}
{% block js %}
{{ js('zamboni/discovery') }}
{% if request.LANG == 'en-US' %}
{{ js('zamboni/discovery-video', defer=True) }}
{% endif %}
{% endblock %}

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

@ -1,28 +0,0 @@
{% set app = request.APP.pretty %}
{% if user.is_authenticated %}
<section id="my-account">
{# L10n: {0} is the user's login name. #}
<p>{{ _('Hi, {0}')|format_html(request.user.welcome_name) }}</p>
<ul>
<li><a href="{{ request.user.get_url_path() }}">{{ _('My Profile') }}</a></li>
<li><a href="{{ url('collections.detail', request.user.username,
'favorites') }}">{{ _('My Favorites') }}</a></li>
<li><a href="{{ url('collections.user', request.user.username) }}">{{ _('My Collections') }}</a></li>
</ul>
<p id="logout"><a href="{{ url('users.logout') }}" target="_self">{{ _('Log out') }}</a></p>
</section>
{% else %}
<section id="mission">
<p>{% trans url="http://www.mozilla.org/" -%}
Thanks for using {{ app }} and supporting
<a href="{{ url }}">Mozilla's mission</a>!
{%- endtrans %}</p>
{% if addon_downloads %}
<p id="download-count">
{{ _('Add-ons downloaded:') }}
<strong>{{ addon_downloads|numberfmt }}</strong>
</p>
{% endif %}
</section>
{% endif %}

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

@ -1,25 +0,0 @@
from django.conf import settings
import jinja2
from django_jinja import library
from olympia.addons.templatetags.jinja_helpers import persona_preview
from olympia.amo.urlresolvers import reverse
from olympia.amo.utils import urlparams
@library.global_function
@jinja2.contextfunction
def disco_persona_preview(context, persona, size='large', linked=True,
extra=None, details=False, title=False,
caption=False, src=None):
url = None
if linked:
url = reverse('discovery.addons.detail', args=[persona.addon.slug])
url = settings.SERVICES_URL + url
if src in ('discovery-video', 'discovery-promo', 'discovery-featured'):
url = urlparams(url, src=src)
return persona_preview(context, persona, size=size, linked=linked,
extra=extra, details=details, title=title,
caption=caption, url=url)

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

@ -1,19 +1,13 @@
from django.core.cache import cache
from django.test.utils import override_settings
from django.utils.encoding import smart_text
from django.utils.translation import trim_whitespace
import mock
from pyquery import PyQuery as pq
from olympia import amo
from olympia.addons.models import (
Addon, AddonDependency, CompatOverride, CompatOverrideRange, Preview)
from olympia.amo.templatetags.jinja_helpers import format_date
from olympia.amo.tests import TestCase, addon_factory, collection_factory
from olympia.amo.tests import (
TestCase, addon_factory, collection_factory, user_factory)
from olympia.amo.urlresolvers import reverse
from olympia.bandwagon.models import MonthlyPick
from olympia.legacy_discovery import views
from olympia.legacy_discovery.forms import DiscoveryModuleForm
from olympia.legacy_discovery.models import DiscoveryModule
@ -42,59 +36,40 @@ class TestModuleAdmin(TestCase):
check()
def test_discovery_module_form_bad_locale(self):
d = dict(app=1, module='xx', locales='fake')
form = DiscoveryModuleForm(d)
data = {
'app': amo.FIREFOX.id,
'module': 'xx',
'locales': 'fake'
}
form = DiscoveryModuleForm(data)
assert form.errors['locales']
def test_discovery_module_form_dedupe(self):
d = dict(app=amo.FIREFOX.id, module='xx', locales='en-US he he fa fa')
form = DiscoveryModuleForm(d)
data = {
'app': amo.FIREFOX.id,
'module': 'xx',
'locales': 'en-US he he fa fa'
}
form = DiscoveryModuleForm(data)
assert form.is_valid()
cleaned_locales = form.cleaned_data['locales'].split()
assert sorted(cleaned_locales) == ['en-US', 'fa', 'he']
def test_module_admin_is_not_redirected_to_firefox_new_page(self):
user = user_factory()
self.grant_permission(user, 'Admin:Tools')
self.client.login(email=user.email)
response = self.client.get(reverse('discovery.module_admin'))
assert response.status_code == 200
class TestUrls(TestCase):
fixtures = ['base/users', 'base/featured', 'addons/featured',
'base/addon_3615']
def test_reverse(self):
assert '/en-US/firefox/discovery/pane/10.0/WINNT' == (
reverse('discovery.pane', kwargs=dict(version='10.0',
platform='WINNT')))
assert '/en-US/firefox/discovery/pane/10.0/WINNT/strict' == (
reverse('discovery.pane', args=('10.0', 'WINNT', 'strict')))
def test_resolve_addon_view(self):
r = self.client.get('/en-US/firefox/discovery/addon/3615', follow=True)
url = reverse('discovery.addons.detail', args=['a3615'])
self.assert3xx(r, url, 301)
def test_resolve_disco_pane(self):
# Redirect to default 'strict' if version < 10.
r = self.client.get('/en-US/firefox/discovery/4.0/Darwin', follow=True)
url = reverse('discovery.pane', args=['4.0', 'Darwin', 'strict'])
self.assert3xx(r, url, 302)
# Redirect to default 'ignore' if version >= 10.
r = self.client.get('/en-US/firefox/discovery/10.0/Darwin',
follow=True)
url = reverse('discovery.pane', args=['10.0', 'Darwin', 'ignore'])
self.assert3xx(r, url, 302)
def test_no_compat_mode(self):
r = self.client.head('/en-US/firefox/discovery/pane/10.0/WINNT')
assert r.status_code == 200
def test_with_compat_mode(self):
r = self.client.head('/en-US/firefox/discovery/pane/10.0/WINNT/strict')
assert r.status_code == 200
r = self.client.head('/en-US/firefox/discovery/pane/10.0/WINNT/normal')
assert r.status_code == 200
r = self.client.head('/en-US/firefox/discovery/pane/10.0/WINNT/ignore')
assert r.status_code == 200
r = self.client.head('/en-US/firefox/discovery/pane/10.0/WINNT/blargh')
assert r.status_code == 404
def test_redirect_to_mozilla_new_page(self):
response = self.client.get('/en-US/firefox/discovery/', follow=False)
self.assertRedirects(
response,
'https://www.mozilla.org/firefox/new/',
status_code=301, fetch_redirect_response=False)
class TestPromos(TestCase):
@ -119,9 +94,6 @@ class TestPromos(TestCase):
DiscoveryModule.objects.create(
app=amo.FIREFOX.id, ordering=2, module='Must-Have Media')
def get_disco_url(self, platform, version):
return reverse('discovery.pane.promos', args=[platform, version])
def get_home_url(self):
return reverse('addons.homepage_promos')
@ -182,41 +154,6 @@ class TestPromos(TestCase):
assert unicode(self.addon2.name) not in content
assert 'This &amp; That' in content
def test_pane_platform_filtering(self):
"""Ensure that the discovery pane is filtered by platform."""
file_ = self.addon1.current_version.all_files[0]
file_.update(platform=amo.PLATFORM_LINUX.id)
assert self.addon1.current_version.supported_platforms == [
amo.PLATFORM_LINUX]
response = self.client.get(self.get_disco_url('10.0', 'Darwin'))
assert response.status_code == 200
assert response.content
content = smart_text(response.content)
assert unicode(self.addon1.name) not in content
assert unicode(self.addon2.name) in content
assert 'This &amp; That' in content
# Make sure aliases are working.
response_mac = self.client.get(self.get_disco_url('10.0', 'mac'))
assert response_mac.status_code == 200
assert response_mac.content == response.content
def test_hidden(self):
DiscoveryModule.objects.all().delete()
response = self.client.get(self.get_disco_url('10.0', 'Darwin'))
assert response.status_code == 200
assert response.content == ''
def test_games_linkified(self):
response = self.client.get(self.get_disco_url('10.0', 'Darwin'))
self._test_response_contains_addons(response)
doc = pq(response.content)
h2_link = doc('h2 a').eq(0)
expected_url = '%s%s' % (
reverse('collections.detail', args=['mozilla', 'games']),
'?src=discovery-promo')
assert h2_link.attr('href') == expected_url
def test_games_linkified_home(self):
response = self.client.get(self.get_home_url(),
{'version': '10.0', 'platform': 'mac'})
@ -228,16 +165,6 @@ class TestPromos(TestCase):
'?src=hp-dl-promo')
assert h2_link.attr('href') == expected_url
def test_musthave_media_linkified(self):
response = self.client.get(self.get_disco_url('10.0', 'Darwin'))
assert response.status_code == 200
doc = pq(response.content)
h2_link = doc('h2 a').eq(1)
expected_url = '%s%s' % (
reverse('collections.detail', args=['mozilla', 'must-have-media']),
'?src=discovery-promo')
assert h2_link.attr('href') == expected_url
def test_musthave_media_linkified_home(self):
response = self.client.get(self.get_home_url(),
{'version': '10.0', 'platform': 'mac'})
@ -257,397 +184,3 @@ class TestPromos(TestCase):
doc = pq(response.content)
assert 'This &amp; That' in doc.html()
assert 'That &amp; This' in doc.html()
class TestPane(TestCase):
fixtures = ['addons/featured', 'base/addon_3615', 'base/collections',
'base/featured', 'base/users',
'bandwagon/featured_collections']
def setUp(self):
super(TestPane, self).setUp()
self.url = reverse('discovery.pane', args=['3.7a1pre', 'Darwin'])
def test_my_account(self):
self.client.login(email='regular@mozilla.com')
r = self.client.get(reverse('discovery.pane.account'))
assert r.status_code == 200
doc = pq(r.content)
s = doc('#my-account')
assert s
a = s.find('a').eq(0)
assert a.attr('href') == reverse('users.profile', args=['regularuser'])
assert a.text() == 'My Profile'
a = s.find('a').eq(1)
assert a.attr('href') == (
reverse('collections.detail', args=['regularuser', 'favorites']))
assert a.text() == 'My Favorites'
a = s.find('a').eq(2)
assert a.attr('href') == (
reverse('collections.user', args=['regularuser']))
assert a.text() == 'My Collections'
def test_mission(self):
r = self.client.get(reverse('discovery.pane.account'))
assert pq(r.content)('#mission')
def test_featured_addons_section(self):
r = self.client.get(self.url)
assert pq(r.content)('#featured-addons h2').text() == (
'Featured Add-ons')
def test_featured_addons(self):
r = self.client.get(self.url)
p = pq(r.content)('#featured-addons')
addon = Addon.objects.get(id=7661)
li = p.find('li[data-guid="%s"]' % addon.guid)
a = li.find('a.addon-title')
url = reverse('discovery.addons.detail', args=[7661])
assert a.attr('href').endswith(url + '?src=discovery-featured'), (
'Unexpected add-on details URL')
assert li.find('h3').text() == unicode(addon.name)
assert li.find('img').attr('src') == addon.icon_url
addon = Addon.objects.get(id=2464)
li = p.find('li[data-guid="%s"]' % addon.guid)
assert li.attr('data-guid') == addon.guid
a = li.find('a.addon-title')
url = reverse('discovery.addons.detail', args=[2464])
assert a.attr('href').endswith(url + '?src=discovery-featured'), (
'Unexpected add-on details URL')
assert li.find('h3').text() == unicode(addon.name)
assert li.find('img').attr('src') == addon.icon_url
def test_featured_personas_section(self):
r = self.client.get(self.url)
h2 = pq(r.content)('#featured-themes h2')
assert h2.text() == 'See all Featured Themes'
assert h2.find('a.all').attr('href') == reverse('browse.personas')
@override_settings(MEDIA_URL='/media/', STATIC_URL='/static/')
def test_featured_personas(self):
addon = Addon.objects.get(id=15679)
r = self.client.get(self.url)
doc = pq(r.content)
featured = doc('#featured-themes')
assert featured.length == 1
# Look for all images that are not icon uploads.
imgs = doc('img:not([src*="/media/"])')
imgs_ok = (pq(img).attr('src').startswith('/static/')
for img in imgs)
assert all(imgs_ok), 'Images must be prefixed with MEDIA_URL!'
featured = doc('#featured-themes')
assert featured.length == 1
a = featured.find('a[data-browsertheme]')
url = reverse('discovery.addons.detail', args=[15679])
assert a.attr('href').endswith(url + '?src=discovery-featured'), (
'Unexpected add-on details URL')
assert a.attr('target') == '_self'
assert featured.find('.addon-title').text() == unicode(addon.name)
class TestDetails(TestCase):
fixtures = ['base/addon_3615', 'base/addon_592']
def setUp(self):
super(TestDetails, self).setUp()
self.addon = self.get_addon()
self.detail_url = reverse('discovery.addons.detail',
args=[self.addon.slug])
self.eula_url = reverse('discovery.addons.eula',
args=[self.addon.slug])
def get_addon(self):
return Addon.objects.get(id=3615)
def test_install_button_eula(self):
doc = pq(self.client.get(self.detail_url).content)
assert doc('#install .install-button').text() == 'Download Now'
assert doc('#install .eula').text() == (
'View End-User License Agreement')
doc = pq(self.client.get(self.eula_url).content)
assert doc('#install .install-button').text() == 'Download Now'
def test_install_button_no_eula(self):
self.addon.update(eula=None)
doc = pq(self.client.get(self.detail_url).content)
assert doc('#install .install-button').text() == 'Download Now'
r = self.client.get(self.eula_url)
self.assert3xx(r, self.detail_url, 302)
def test_dependencies(self):
doc = pq(self.client.get(self.detail_url).content)
assert doc('.dependencies').length == 0
req = Addon.objects.get(id=592)
AddonDependency.objects.create(addon=self.addon, dependent_addon=req)
assert self.addon.all_dependencies == [req]
cache.clear()
d = pq(self.client.get(self.detail_url).content)('.dependencies')
assert d.length == 1
a = d.find('ul a')
assert a.text() == unicode(req.name)
assert a.attr('href').endswith('?src=discovery-dependencies')
class TestPersonaDetails(TestCase):
fixtures = ['addons/persona', 'base/users']
def setUp(self):
super(TestPersonaDetails, self).setUp()
self.addon = Addon.objects.get(id=15663)
self.url = reverse('discovery.addons.detail', args=[self.addon.slug])
def test_page(self):
r = self.client.get(self.url)
assert r.status_code == 200
def test_by(self):
"""Test that the `by ... <authors>` section works."""
r = self.client.get(self.url)
assert pq(r.content)('h2.author').text().startswith(
'by persona_author')
def test_no_version(self):
"""Don't display a version number for themes."""
r = self.client.get(self.url)
assert pq(r.content)('h1 .version') == []
def test_created_not_updated(self):
"""Don't display the updated date but the created date for themes."""
r = self.client.get(self.url)
doc = pq(r.content)
details = doc('.addon-info li')
# There's no "Last Updated" entry.
assert not any('Last Updated' in node.text_content()
for node in details)
# But there's a "Created" entry.
for detail in details:
if detail.find('h3').text_content() == 'Created':
created = detail.find('p').text_content()
assert created == (
trim_whitespace(format_date(self.addon.created)))
break # Needed, or we go in the "else" clause.
else:
assert False, 'No "Created" entry found.'
class TestDownloadSources(TestCase):
fixtures = ['base/addon_3615', 'base/users',
'base/collections', 'base/featured', 'addons/featured',
'legacy_discovery/discoverymodules']
def setUp(self):
super(TestDownloadSources, self).setUp()
self.url = reverse('discovery.pane', args=['3.7a1pre', 'Darwin'])
def test_detail(self):
url = reverse('discovery.addons.detail', args=['a3615'])
r = self.client.get(url)
doc = pq(r.content)
assert doc('#install a.download').attr('href').endswith(
'?src=discovery-details')
assert doc('#install li a#learn-more').attr('href').endswith(
'?src=discovery-learnmore')
assert doc('#install li.privacy a').attr('href').endswith(
'?src=discovery-learnmore')
def test_detail_trickle(self):
url = (reverse('discovery.addons.detail', args=['a3615']) +
'?src=discovery-featured')
r = self.client.get(url)
doc = pq(r.content)
assert doc('#install a.download').attr('href').endswith(
'?src=discovery-featured')
def test_eula(self):
url = reverse('discovery.addons.eula', args=['a3615'])
r = self.client.get(url)
doc = pq(r.content)
assert doc('#install a.download').attr('href').endswith(
'?src=discovery-details')
assert doc('#install li:eq(1)').find('a').attr('href').endswith(
'?src=discovery-details')
def test_eula_trickle(self):
url = (reverse('discovery.addons.eula', args=['a3615']) +
'?src=discovery-upandcoming')
r = self.client.get(url)
doc = pq(r.content)
assert doc('#install a.download').attr('href').endswith(
'?src=discovery-upandcoming')
assert doc('#install li:eq(1)').find('a').attr('href').endswith(
'?src=discovery-upandcoming')
class TestTestPilot(TestCase):
fixtures = ['base/users', 'base/addon_3615',
'legacy_discovery/discoverymodules']
def setUp(self):
super(TestTestPilot, self).setUp()
self.url = reverse('discovery.pane.promos', args=['Darwin', '10.0'])
self.addon = Addon.objects.get(id=3615)
DiscoveryModule.objects.create(
app=amo.FIREFOX.id, ordering=4,
module='Test Pilot')
def test_testpilot(self):
r = self.client.get(self.url)
assert pq(r.content)('h2').text() == 'Become a Test Pilot'
assert (pq(r.content)('h3').text() ==
'Unlock early access to experimental browser features.')
assert (pq(r.content)('a').attr('href') ==
'https://testpilot.firefox.com/')
class TestMonthlyPick(TestCase):
fixtures = ['base/users', 'base/addon_3615',
'legacy_discovery/discoverymodules']
def setUp(self):
super(TestMonthlyPick, self).setUp()
self.url = reverse('discovery.pane.promos', args=['Darwin', '10.0'])
self.addon = Addon.objects.get(id=3615)
DiscoveryModule.objects.create(
app=amo.FIREFOX.id, ordering=4,
module='Monthly Pick')
def test_monthlypick(self):
# First test with locale=None, it should never appear.
mp = MonthlyPick.objects.create(addon=self.addon, blurb='BOOP',
image='http://mozilla.com')
response = self.client.get(self.url)
assert response.content == ''
# Now update with locale='', it should be used as the fallback.
mp.update(locale='')
response = self.client.get(self.url)
pick = pq(response.content)('#monthly')
assert pick.length == 1
assert pick.parents('.panel').attr('data-addonguid') == self.addon.guid
a = pick.find('h3 a')
url = reverse('discovery.addons.detail', args=['a3615'])
assert a.attr('href').endswith(url + '?src=discovery-promo'), (
'Unexpected add-on details URL: %s' % url)
assert a.attr('target') == '_self'
assert a.text() == unicode(self.addon.name)
assert pick.find('img').attr('src') == 'http://mozilla.com'
assert pick.find('.wrap > div > div > p').text() == 'BOOP'
assert pick.find('p.install-button a').attr('href').endswith(
'?src=discovery-promo')
def test_monthlypick_disabled_addon(self):
disabled_addon = addon_factory(disabled_by_user=True)
MonthlyPick.objects.create(
addon=disabled_addon, blurb='foo', locale='en-US')
MonthlyPick.objects.create(
addon=self.addon, blurb='bar', locale='')
response = self.client.get(self.url)
pick = pq(response.content)('#monthly')
assert pick.length == 1
assert pick.parents('.panel').attr('data-addonguid') == self.addon.guid
def test_monthlypick_no_image(self):
MonthlyPick.objects.create(addon=self.addon, blurb='BOOP', locale='',
image='')
# Tests for no image when screenshot not set.
r = self.client.get(self.url)
pick = pq(r.content)('#monthly')
assert pick.length == 1
assert pick.find('img').length == 0
# Tests for screenshot image when set.
Preview.objects.create(addon=self.addon)
del self.addon._all_previews
r = self.client.get(self.url)
pick = pq(r.content)('#monthly')
assert pick.length == 1
assert pick.find('img').attr('src') == (
self.addon.current_previews[0].image_url)
def test_no_monthlypick(self):
r = self.client.get(self.url)
assert r.content == ''
class TestPaneMoreAddons(TestCase):
fixtures = ['base/appversion']
def setUp(self):
super(TestPaneMoreAddons, self).setUp()
self.addon1 = addon_factory(hotness=99,
version_kw=dict(max_app_version='5.0'))
self.addon2 = addon_factory(hotness=0,
version_kw=dict(max_app_version='6.0'))
def _url(self, **kwargs):
default = dict(
section='up-and-coming',
version='5.0',
platform='Darwin')
default.update(kwargs)
return reverse('discovery.pane.more_addons', kwargs=default)
def test_hotness_strict(self):
# Defaults to strict compat mode, both are within range.
res = self.client.get(self._url())
assert res.status_code == 200
assert pq(res.content)('.featured-addons').length == 2
def test_hotness_strict_filtered(self):
# Defaults to strict compat mode, one is within range.
res = self.client.get(self._url(version='6.0'))
assert res.status_code == 200
assert pq(res.content)('.featured-addons').length == 1
self.assertContains(res, self.addon2.name)
def test_hotness_ignore(self):
# Defaults to ignore compat mode for Fx v10, both are compatible.
res = self.client.get(self._url(version='10.0'))
assert res.status_code == 200
assert pq(res.content)('.featured-addons').length == 2
def test_hotness_normal_strict_opt_in(self):
# Add a 3rd add-on that should get filtered out b/c of compatibility.
addon_factory(hotness=50, version_kw=dict(max_app_version='7.0'),
file_kw=dict(strict_compatibility=True))
res = self.client.get(self._url(version='12.0', compat_mode='normal'))
assert res.status_code == 200
assert pq(res.content)('.featured-addons').length == 2
def test_hotness_normal_binary_components(self):
# Add a 3rd add-on that should get filtered out b/c of compatibility.
addon_factory(hotness=50, version_kw=dict(max_app_version='7.0'),
file_kw=dict(binary_components=True))
res = self.client.get(self._url(version='12.0', compat_mode='normal'))
assert res.status_code == 200
assert pq(res.content)('.featured-addons').length == 2
def test_hotness_normal_compat_override(self):
# Add a 3rd add-on that should get filtered out b/c of compatibility.
addon3 = addon_factory(hotness=50,
version_kw=dict(max_app_version='7.0'))
# Add override for this add-on.
compat = CompatOverride.objects.create(guid='three', addon=addon3)
CompatOverrideRange.objects.create(
compat=compat, app=1,
min_version=addon3.current_version.version, max_version='*')
res = self.client.get(self._url(version='12.0', compat_mode='normal'))
assert res.status_code == 200
assert pq(res.content)('.featured-addons').length == 2

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

@ -1,46 +1,11 @@
from django.conf.urls import include, url
from django.urls import reverse
from django.db.transaction import non_atomic_requests
from django.conf.urls import url
from django.shortcuts import redirect
from olympia.addons.urls import ADDON_ID
from . import views
# These will all start with /addon/<addon_id>/
addon_patterns = [
url('^$', views.addon_detail, name='discovery.addons.detail'),
url('^eula/(?P<file_id>\d+)?$', views.addon_eula,
name='discovery.addons.eula'),
]
browser_re = '(?P<version>[^/]+)/(?P<platform>[^/]+)'
compat_mode_re = '(?:/(?P<compat_mode>strict|normal|ignore))?'
@non_atomic_requests
def pane_redirect(req, **kw):
kw['compat_mode'] = views.get_compat_mode(kw.get('version'))
return redirect(reverse('discovery.pane', kwargs=kw), permanent=False)
from .views import module_admin
urlpatterns = [
# Force the match so this doesn't get picked up by the wide open
# /:version/:platform regex.
url('^addon/%s$' % ADDON_ID,
lambda r, addon_id: redirect('discovery.addons.detail',
addon_id, permanent=True)),
url('^addon/%s/' % ADDON_ID, include(addon_patterns)),
url('^pane/account$', views.pane_account, name='discovery.pane.account'),
url('^pane/(?P<section>featured|up-and-coming)/%s$' % (
browser_re + compat_mode_re), views.pane_more_addons,
name='discovery.pane.more_addons'),
url('^%s$' % (browser_re + compat_mode_re), pane_redirect),
url('^pane/%s$' % (browser_re + compat_mode_re), views.pane,
name='discovery.pane'),
url('^pane/promos/%s$' % (browser_re + compat_mode_re), views.pane_promos,
name='discovery.pane.promos'),
url('^modules$', views.module_admin, name='discovery.module_admin'),
url('^modules$', module_admin, name='discovery.module_admin'),
url('^.*', lambda request: redirect(
'https://www.mozilla.org/firefox/new/', permanent=True)),
]

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

@ -1,73 +1,14 @@
import json
from django import http
from django.db.transaction import non_atomic_requests
from django.forms.models import modelformset_factory
from django.shortcuts import get_object_or_404, redirect
import olympia.core.logger
from django.shortcuts import redirect
from olympia import amo
from olympia.addons.decorators import addon_view_factory
from olympia.addons.models import Addon
from olympia.addons.utils import get_featured_ids
from olympia.amo.models import manual_order
from olympia.amo.urlresolvers import reverse
from olympia.amo.utils import render
from olympia.browse.views import personas_listing
from olympia.legacy_api import views as legacy_api_views
from olympia.ratings.models import Rating
from olympia.stats.models import GlobalStat
from olympia.versions.compare import version_int
from olympia.zadmin.decorators import admin_required
from .forms import DiscoveryModuleForm
from .models import DiscoveryModule
from .modules import PromoVideoCollection, registry as module_registry
addon_view = addon_view_factory(Addon.objects.valid)
log = olympia.core.logger.getLogger('z.disco')
def get_compat_mode(version):
# Returns appropriate compat mode based on app version.
# Replace when we are ready to deal with bug 711698.
vint = version_int(version)
return 'ignore' if vint >= version_int('10.0') else 'strict'
@non_atomic_requests
def pane(request, version, platform, compat_mode=None):
if not compat_mode:
compat_mode = get_compat_mode(version)
def from_api(list_type):
return api_view(request, platform, version, list_type,
compat_mode=compat_mode)
promovideo = PromoVideoCollection().get_items()
return render(request, 'legacy_discovery/pane.html',
{'up_and_coming': from_api('hotness'),
'featured_addons': from_api('featured'),
'featured_personas': get_featured_personas(request),
'version': version, 'platform': platform,
'promovideo': promovideo, 'compat_mode': compat_mode})
@non_atomic_requests
def pane_account(request):
try:
qs = GlobalStat.objects.filter(name='addon_total_downloads')
addon_downloads = qs.latest().count
except GlobalStat.DoesNotExist:
addon_downloads = None
return render(request, 'legacy_discovery/pane_account.html',
{'addon_downloads': addon_downloads})
from .modules import registry as module_registry
@non_atomic_requests
@ -77,34 +18,7 @@ def promos(request, context, version, platform, compat_mode='strict'):
platform = amo.PLATFORM_DICT.get(platform, amo.PLATFORM_ALL)
modules = get_modules(request, platform.api_name, version)
return render(request, 'addons/impala/homepage_promos.html',
{'modules': modules, 'module_context': context})
@non_atomic_requests
def pane_promos(request, version, platform, compat_mode=None):
if not compat_mode:
compat_mode = get_compat_mode(version)
return promos(request, 'discovery', version, platform, compat_mode)
@non_atomic_requests
def pane_more_addons(request, section, version, platform, compat_mode=None):
if not compat_mode:
compat_mode = get_compat_mode(version)
def from_api(list_type):
return api_view(request, platform, version, list_type,
compat_mode=compat_mode)
ctx = {}
if section == 'featured':
ctx = {'featured_addons': from_api('featured')}
elif section == 'up-and-coming':
ctx = {'up_and_coming': from_api('hotness')}
content = render(request, 'legacy_discovery/more_addons.html', ctx)
return content
{'modules': modules})
def get_modules(request, platform, version):
@ -121,26 +35,6 @@ def get_modules(request, platform, version):
for m in modules]
def get_featured_personas(request, category=None, num_personas=6):
categories, filter, base, category = personas_listing(request, category)
ids = get_featured_ids(request.APP, request.LANG, type=amo.ADDON_PERSONA)
return manual_order(base, ids, 'addons.id')[:num_personas]
@non_atomic_requests
def api_view(request, platform, version, list_type, api_version=1.5,
format='json', content_type='application/json',
compat_mode='strict'):
"""Wrapper for calling an API view."""
view = legacy_api_views.ListView()
view.request, view.version = request, api_version
view.format, view.content_type = format, content_type
r = view.process_request(list_type, platform=platform, version=version,
compat_mode=compat_mode)
return json.loads(r.content)
@admin_required
@non_atomic_requests
def module_admin(request):
@ -174,28 +68,3 @@ def _sync_db_and_registry(qs, app_id):
DiscoveryModule.objects.filter(module__in=to_delete, app=app_id).delete()
if to_add or to_delete:
qs._result_cache = None
@addon_view
@non_atomic_requests
def addon_detail(request, addon):
reviews = Rating.without_replies.all().filter(addon=addon, is_latest=True)
src = request.GET.get('src', 'discovery-details')
return render(request, 'legacy_discovery/addons/detail.html',
{'addon': addon, 'reviews': reviews,
'get_replies': Rating.get_replies, 'src': src})
@addon_view
@non_atomic_requests
def addon_eula(request, addon, file_id):
if not addon.eula:
return http.HttpResponseRedirect(reverse('discovery.addons.detail',
args=[addon.slug]))
if file_id is not None:
version = get_object_or_404(addon.versions, files__id=file_id)
else:
version = addon.current_version
src = request.GET.get('src', 'discovery-details')
return render(request, 'legacy_discovery/addons/eula.html',
{'addon': addon, 'version': version, 'src': src})