Skip to content

Commit

Permalink
add <addon_compatibility> to the guid search API (bug 692971)
Browse files Browse the repository at this point in the history
  • Loading branch information
Jeff Balogh committed Oct 14, 2011
1 parent 5fcf72e commit 69c6f14
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 4 deletions.
4 changes: 4 additions & 0 deletions apps/addons/models.py
Expand Up @@ -1557,6 +1557,10 @@ def __unicode__(self):
else:
return self.guid

def is_hosted(self):
"""Am I talking about an add-on on AMO?"""
return bool(self.addon_id)

@staticmethod
def transformer(overrides):
if not overrides:
Expand Down
8 changes: 8 additions & 0 deletions apps/addons/tests/test_models.py
Expand Up @@ -1767,6 +1767,14 @@ def check(self, obj, **kw):
actual = getattr(obj, key)
eq_(actual, expected, '[%s] %r != %r' % (key, actual, expected))

def test_is_hosted(self):
c = CompatOverride.objects.create(guid='a')
assert not c.is_hosted()

a = Addon.objects.create(type=1, guid='b')
c = CompatOverride.objects.create(guid='b')
assert c.is_hosted()

def test_guid_match(self):
# We hook up the add-on automatically if we see a matching guid.
addon = Addon.objects.create(id=1, guid='oh yeah', type=1)
Expand Down
27 changes: 27 additions & 0 deletions apps/api/templates/api/compat.xml
@@ -0,0 +1,27 @@
{% for c in compat %}
<addon_compatibility
hosted="{{ c.is_hosted()|json }}"
{% if c.addon_id %}id="{{ c.addon_id }}"{% endif %}>
<guid>{{ c.guid }}</guid>
<name>{{ c.name }}</name>
<version_ranges>
{% for vr in c.collapsed_ranges() %}
<version_range>
<min_version>{{ vr.min }}</min_version>
<max_version>{{ vr.max }}</max_version>
<compatible_applications>
{% for app in vr.apps %}
<application>
<name>{{ app.app.pretty }}</name>
<application_id>{{ app.app.id }}</application_id>
<min_version>{{ app.min }}</min_version>
<max_version>{{ app.max }}</max_version>
<appID>{{ app.app.guid }}</appID>
</application>
{% endfor %}
</compatible_applications>
</version_range>
{% endfor %}
</version_ranges>
</addon_compatibility>
{% endfor %}
1 change: 1 addition & 0 deletions apps/api/templates/api/search.xml
Expand Up @@ -3,4 +3,5 @@
{% for addon in results -%}
{% include 'api/includes/addon.xml' -%}
{% endfor %}
{% if compat %}{% include 'api/compat.xml' %}{% endif %}
</searchresults>
55 changes: 53 additions & 2 deletions apps/api/tests/test_views.py
Expand Up @@ -20,7 +20,8 @@
from amo.tests import TestCase
from amo.urlresolvers import reverse
from addons.cron import reset_featured_addons
from addons.models import (Addon, AppSupport, Feature, Preview)
from addons.models import (Addon, AppSupport, CompatOverride,
CompatOverrideRange, Feature, Preview)
from addons.utils import FeaturedManager
from applications.models import Application
from bandwagon.models import Collection, CollectionAddon, FeaturedCollection
Expand Down Expand Up @@ -619,11 +620,21 @@ def test_seamonkey_wankery(self):
class TestGuidSearch(TestCase):
fixtures = ('base/apps', 'base/addon_6113', 'base/addon_3615')

def setUp(self):
addon = Addon.objects.get(id=3615)
c = CompatOverride.objects.create(guid=addon.guid)
app = addon.compatible_apps.keys()[0]
CompatOverrideRange.objects.create(compat=c, app_id=app.id)

def test_success(self):
r = make_call('search/guid:{22870005-adef-4c9d-ae36-d0e1f2f27e5a},'
'{2fa4ed95-0317-4c6a-a74c-5f3e3912c1f9}')
dom = pq(r.content)
eq_(set(['3615', '6113']),
set([a.attrib['id'] for a in pq(r.content)('addon')]))
set([a.attrib['id'] for a in dom('addon')]))

# Make sure the <addon_compatibility> blocks are there.
eq_(['3615'], [a.attrib['id'] for a in dom('addon_compatibility')])

def test_block_inactive(self):
Addon.objects.filter(id=6113).update(disabled_by_user=True)
Expand All @@ -650,6 +661,46 @@ def test_empty(self):
# indicate that we are searching for null guid.
eq_(len(doc('addon')), 0)

def test_addon_compatibility(self):
addon = Addon.objects.get(id=3615)
r = make_call('search/guid:%s' % addon.guid)
dom = pq(r.content)
eq_(len(dom('addon_compatibility')), 1)
eq_(dom('addon_compatibility')[0].attrib['id'], '3615')
eq_(dom('addon_compatibility')[0].attrib['hosted'], 'true')

eq_(dom('addon_compatibility guid').text(), addon.guid)
eq_(dom('addon_compatibility > name').text(), '')

eq_(dom('addon_compatibility version_ranges version_range '
'compatible_applications application appID').text(),
amo.FIREFOX.guid)

def test_addon_compatibility_not_hosted(self):
c = CompatOverride.objects.create(guid='yeah', name='ok')
CompatOverrideRange.objects.create(app_id=1, compat=c,
min_version='1', max_version='2',
min_app_version='3',
max_app_version='4')

r = make_call('search/guid:%s' % c.guid)
dom = pq(r.content)
eq_(len(dom('addon_compatibility')), 1)
eq_(dom('addon_compatibility')[0].attrib['hosted'], 'false')
assert 'id' not in dom('addon_compatibility')[0].attrib

eq_(dom('addon_compatibility guid').text(), c.guid)
eq_(dom('addon_compatibility > name').text(), c.name)

cr = c.compat_ranges[0]
eq_(dom('version_range > min_version').text(), cr.min_version)
eq_(dom('version_range > max_version').text(), cr.max_version)
eq_(dom('application name').text(), amo.FIREFOX.pretty)
eq_(dom('application application_id').text(), str(amo.FIREFOX.id))
eq_(dom('application appID').text(), amo.FIREFOX.guid)
eq_(dom('application min_version').text(), cr.min_app_version)
eq_(dom('application max_version').text(), cr.max_app_version)


class SearchTest(SphinxTestCase):
fixtures = ('base/apps', 'base/addon_6113', 'base/addon_40',
Expand Down
7 changes: 5 additions & 2 deletions apps/api/views.py
Expand Up @@ -21,9 +21,9 @@
from amo.models import manual_order
from amo.urlresolvers import get_url_prefix
from amo.utils import JSONEncoder
from addons.models import Addon
from addons.models import Addon, CompatOverride
from search.client import (Client as SearchClient, SearchError,
extract_from_query, SEARCHABLE_STATUSES)
SEARCHABLE_STATUSES)
from search import utils as search_utils

ERROR = 'error'
Expand Down Expand Up @@ -204,8 +204,11 @@ def guid_search(request, api_version, guids):
guids = [g.strip() for g in guids.split(',')] if guids else []
results = Addon.objects.filter(guid__in=guids, disabled_by_user=False,
status__in=SEARCHABLE_STATUSES)
compat = (CompatOverride.objects.filter(guid__in=guids)
.transform(CompatOverride.transformer))
return render_xml(request, 'api/search.xml',
{'results': results, 'total': len(results),
'compat': compat,
'api_version': api_version, 'api': api})


Expand Down

0 comments on commit 69c6f14

Please sign in to comment.