2010-05-03 22:31:37 +04:00
|
|
|
import json
|
|
|
|
|
|
|
|
from django import test
|
|
|
|
|
2010-05-04 08:36:03 +04:00
|
|
|
import mock
|
2010-05-03 22:31:37 +04:00
|
|
|
from nose.tools import eq_
|
|
|
|
import test_utils
|
|
|
|
|
2010-05-04 08:10:56 +04:00
|
|
|
import amo
|
2010-09-25 03:07:50 +04:00
|
|
|
import amo.test_utils
|
2010-05-03 22:31:37 +04:00
|
|
|
from amo.urlresolvers import reverse
|
2010-05-05 09:07:31 +04:00
|
|
|
from applications.models import Application
|
2010-05-04 20:47:38 +04:00
|
|
|
from bandwagon.models import Collection, SyncedCollection, CollectionToken
|
2010-05-04 08:36:03 +04:00
|
|
|
from discovery import views
|
2010-05-05 09:07:31 +04:00
|
|
|
from discovery.forms import DiscoveryModuleForm
|
|
|
|
from discovery.models import DiscoveryModule
|
|
|
|
from discovery.modules import registry
|
2010-05-03 22:31:37 +04:00
|
|
|
|
|
|
|
|
2010-09-25 03:07:50 +04:00
|
|
|
class RecsTest(amo.test_utils.ExtraSetup, test_utils.TestCase):
|
|
|
|
fixtures = ['base/apps', 'base/appversion', 'base/addon-recs',
|
|
|
|
'base/addon_5299_gcal', 'base/category', 'base/featured']
|
2010-05-03 22:31:37 +04:00
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def setup_class(cls):
|
|
|
|
test.Client().get('/')
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
self.url = reverse('discovery.recs')
|
2010-08-11 23:49:46 +04:00
|
|
|
self.guids = ('bettergcal@ginatrapani.org',
|
2010-05-04 20:47:38 +04:00
|
|
|
'foxyproxy@eric.h.jung',
|
|
|
|
'isreaditlater@ideashower.com',
|
2010-08-11 23:49:46 +04:00
|
|
|
'not-a-real-guid',)
|
|
|
|
self.ids = [5299, 2464, 7661]
|
2010-05-04 20:47:38 +04:00
|
|
|
self.json = json.dumps({'guids': self.guids})
|
|
|
|
# Found in bandwagon.TestRecommendations.expected_recs.
|
|
|
|
self.expected_recs = [6249, 7661, 6665, 4781, 6366]
|
2010-05-03 22:31:37 +04:00
|
|
|
|
|
|
|
def test_get(self):
|
|
|
|
"""GET should find method not allowed."""
|
|
|
|
response = self.client.get(self.url)
|
|
|
|
eq_(response.status_code, 405)
|
2010-05-03 22:34:30 +04:00
|
|
|
|
|
|
|
def test_empty_post_data(self):
|
|
|
|
response = self.client.post(self.url)
|
|
|
|
eq_(response.status_code, 400)
|
|
|
|
|
|
|
|
def test_bad_post_data(self):
|
2010-05-04 20:47:38 +04:00
|
|
|
response = self.client.post(self.url, '{]{',
|
|
|
|
content_type='application/json')
|
|
|
|
eq_(response.status_code, 400)
|
|
|
|
|
|
|
|
def test_no_guids(self):
|
|
|
|
response = self.client.post(self.url, '{}',
|
2010-05-03 22:34:30 +04:00
|
|
|
content_type='application/json')
|
|
|
|
eq_(response.status_code, 400)
|
2010-05-03 22:42:36 +04:00
|
|
|
|
|
|
|
def test_get_addon_ids(self):
|
2010-05-04 08:36:03 +04:00
|
|
|
ids = set(views.get_addon_ids(self.guids))
|
2010-05-04 08:10:56 +04:00
|
|
|
eq_(ids, set(self.ids))
|
|
|
|
|
|
|
|
def test_get_synced_collection(self):
|
|
|
|
# Get a fresh synced collection.
|
2010-05-04 08:36:03 +04:00
|
|
|
c = views.get_synced_collection(self.ids, 'token')
|
2010-05-04 08:10:56 +04:00
|
|
|
eq_(c.listed, False)
|
|
|
|
eq_(c.type, amo.COLLECTION_SYNCHRONIZED)
|
|
|
|
eq_(set(c.addons.values_list('id', flat=True)), set(self.ids))
|
|
|
|
|
|
|
|
# Check that the token was set.
|
|
|
|
eq_(c.token_set.get().token, 'token')
|
|
|
|
|
|
|
|
# Make sure we get the same collection if we try again.
|
2010-05-04 08:36:03 +04:00
|
|
|
next = views.get_synced_collection(self.ids, 'next')
|
2010-05-04 08:10:56 +04:00
|
|
|
eq_(next.id, c.id)
|
|
|
|
eq_(set(next.addons.values_list('id', flat=True)), set(self.ids))
|
|
|
|
eq_(list(c.token_set.values_list('token', flat=True)),
|
|
|
|
['token', 'next'])
|
|
|
|
|
|
|
|
def test_get_synced_collection_with_dupes(self):
|
|
|
|
"""It shouldn't happen, but make sure we handled synced dupes."""
|
|
|
|
one = SyncedCollection.objects.create()
|
|
|
|
one.set_addons(self.ids)
|
|
|
|
two = SyncedCollection.objects.create()
|
|
|
|
two.set_addons(self.ids)
|
|
|
|
|
2010-05-04 08:36:03 +04:00
|
|
|
three = views.get_synced_collection(self.ids, 'token')
|
2010-05-04 08:10:56 +04:00
|
|
|
assert one.addon_index == two.addon_index == three.addon_index
|
2010-05-04 08:36:03 +04:00
|
|
|
|
|
|
|
@mock.patch('discovery.views.uuid.uuid4')
|
|
|
|
def test_get_random_token(self, uuid_mock):
|
|
|
|
uuid_mock.side_effect = ['two', 'one', 'one', 'one'].pop
|
|
|
|
eq_(views.get_random_token(), 'one')
|
|
|
|
views.get_synced_collection([], 'one')
|
|
|
|
eq_(views.get_random_token(), 'two')
|
2010-05-04 19:44:59 +04:00
|
|
|
|
|
|
|
def test_success(self):
|
|
|
|
response = self.client.post(self.url, self.json,
|
|
|
|
content_type='application/json')
|
|
|
|
eq_(response.status_code, 200)
|
|
|
|
eq_(response['Content-type'], 'application/json')
|
|
|
|
data = json.loads(response.content)
|
|
|
|
|
|
|
|
eq_(set(data.keys()), set(['token', 'recommendations', 'addons']))
|
|
|
|
eq_(len(data['addons']), 5)
|
2010-05-04 20:47:38 +04:00
|
|
|
ids = [a['id'] for a in data['addons']]
|
|
|
|
eq_(ids, self.expected_recs)
|
2010-05-04 19:44:59 +04:00
|
|
|
|
|
|
|
# Our token should match a synced collection, and that collection's
|
|
|
|
# recommendations should match what we got.
|
|
|
|
q = SyncedCollection.objects.filter(token_set__token=data['token'])
|
|
|
|
eq_(len(q), 1)
|
|
|
|
eq_(q[0].recommended_collection.get_url_path(),
|
|
|
|
data['recommendations'])
|
2010-05-04 20:47:38 +04:00
|
|
|
|
|
|
|
def test_recs_bad_token(self):
|
|
|
|
post_data = json.dumps(dict(guids=self.guids, token='fake'))
|
|
|
|
response = self.client.post(self.url, post_data,
|
|
|
|
content_type='application/json')
|
|
|
|
data = json.loads(response.content)
|
|
|
|
ids = [a['id'] for a in data['addons']]
|
|
|
|
eq_(ids, self.expected_recs)
|
|
|
|
|
|
|
|
def test_update_same_index(self):
|
|
|
|
response = self.client.post(self.url, self.json,
|
|
|
|
content_type='application/json')
|
|
|
|
one = json.loads(response.content)
|
|
|
|
|
|
|
|
post_data = json.dumps(dict(guids=self.guids, token=one['token']))
|
|
|
|
response = self.client.post(self.url, post_data,
|
|
|
|
content_type='application/json')
|
|
|
|
eq_(response.status_code, 200)
|
|
|
|
two = json.loads(response.content)
|
|
|
|
|
|
|
|
# We sent our existing token and the same ids, so the
|
|
|
|
# responses should be identical.
|
|
|
|
eq_(one, two)
|
|
|
|
|
|
|
|
eq_(CollectionToken.objects.count(), 1)
|
|
|
|
|
|
|
|
def test_update_new_index(self):
|
|
|
|
response = self.client.post(self.url, self.json,
|
|
|
|
content_type='application/json')
|
|
|
|
one = json.loads(response.content)
|
|
|
|
|
|
|
|
post_data = json.dumps(dict(guids=self.guids[:1], token=one['token']))
|
|
|
|
response = self.client.post(self.url, post_data,
|
|
|
|
content_type='application/json')
|
|
|
|
eq_(response.status_code, 200)
|
|
|
|
two = json.loads(response.content)
|
|
|
|
|
|
|
|
eq_(one['token'], two['token'])
|
|
|
|
assert one['recommendations'] != two['recommendations']
|
|
|
|
assert one['addons'] != two['addons']
|
|
|
|
eq_(CollectionToken.objects.count(), 1)
|
|
|
|
eq_(len(Collection.objects.filter(type=amo.COLLECTION_SYNCHRONIZED)),
|
2010-08-11 23:49:46 +04:00
|
|
|
2)
|
2010-05-05 09:07:31 +04:00
|
|
|
|
|
|
|
|
|
|
|
class TestModuleAdmin(test_utils.TestCase):
|
2010-08-11 23:49:46 +04:00
|
|
|
fixtures = ('base/apps', )
|
2010-05-05 09:07:31 +04:00
|
|
|
|
|
|
|
def test_sync_db_and_registry(self):
|
|
|
|
def check():
|
|
|
|
views._sync_db_and_registry(qs, app)
|
|
|
|
eq_(qs.count(), len(registry))
|
|
|
|
modules = qs.values_list('module', flat=True)
|
|
|
|
eq_(set(modules), set(registry.keys()))
|
|
|
|
|
|
|
|
app = Application.objects.create()
|
|
|
|
qs = DiscoveryModule.uncached.filter(app=app)
|
|
|
|
eq_(qs.count(), 0)
|
|
|
|
|
|
|
|
# All our modules get added.
|
|
|
|
check()
|
|
|
|
|
|
|
|
# The deleted module is removed.
|
|
|
|
registry.popitem()
|
|
|
|
check()
|
|
|
|
|
|
|
|
def test_discovery_module_form_bad_locale(self):
|
|
|
|
d = dict(app=1, module='xx', locales='fake')
|
|
|
|
form = DiscoveryModuleForm(d)
|
|
|
|
assert form.errors['locales']
|
|
|
|
|
|
|
|
|
|
|
|
def test_discovery_module_form_dedupe(self):
|
2010-08-11 23:49:46 +04:00
|
|
|
d = dict(app=amo.FIREFOX.id, module='xx', locales='en-US he he fa fa')
|
2010-05-05 09:07:31 +04:00
|
|
|
form = DiscoveryModuleForm(d)
|
|
|
|
assert form.is_valid()
|
|
|
|
eq_(form.cleaned_data['locales'], 'fa en-US he')
|