def test_feature_compatibility_no_current_version(self): self.app._current_version = None feature_profile = FeatureProfile(apps=True, nfc=True, mobileid=True) self.request = RequestFactory().get( '/?dev=firefoxos&pro=%s' % feature_profile.to_signature()) res = self.serialize(self.app) eq_(res['feature_compatibility'], None)
def test_from_old_signature(self): profile = FeatureProfile.from_signature(self.signature) self._test_profile_values(profile) new_signature = profile.to_signature() ok_(new_signature != self.signature) profile = FeatureProfile.from_signature(new_signature) self._test_profile_values(profile)
def test_feature_compatibility_no_current_version(self): self.app._current_version = None feature_profile = FeatureProfile(apps=True, nfc=True, mobileid=True) self.request = RequestFactory().get('/?dev=firefoxos&pro=%s' % feature_profile.to_signature()) res = self.serialize(self.app) eq_(res['feature_compatibility'], None)
def test_feature_compatibility_false(self): self.app.current_version.features.update(has_apps=True, has_nfc=True) feature_profile = FeatureProfile(apps=False, nfc=True, mobileid=True) self.request = RequestFactory().get( '/?dev=firefoxos&pro=%s' % feature_profile.to_signature()) res = self.serialize(self.app) eq_(res['feature_compatibility'], False)
def profile_qs(self, disabled_features=None): if disabled_features is None: disabled_features = {} profile = FeatureProfile().fromkeys(FeatureProfile(), True) for feature in disabled_features: profile[feature] = False return {'pro': profile.to_signature(), 'dev': 'firefoxos'}
def test_feature_compatibility_false(self): self.app.current_version.features.update(has_apps=True, has_nfc=True) feature_profile = FeatureProfile(apps=False, nfc=True, mobileid=True) self.request = RequestFactory().get('/?dev=firefoxos&pro=%s' % feature_profile.to_signature()) res = self.serialize(self.app) eq_(res['feature_compatibility'], False)
def test_feature_compatibility_always_none(self): # ES is already filtering by feature profile for us, so it does not # make much sense to check for feature compatibility in ES serializer. self.app.current_version.features.update(has_apps=True, has_nfc=True) self.reindex(Webapp) feature_profile = FeatureProfile(apps=False, nfc=True, mobileid=True) self.request = RequestFactory().get('/?dev=firefoxos&pro=%s' % feature_profile.to_signature()) self.request.REGION = mkt.regions.USA self.request.user = self.profile res = self.serialize() eq_(res['feature_compatibility'], None)
def test_feature_compatibility_always_none(self): # ES is already filtering by feature profile for us, so it does not # make much sense to check for feature compatibility in ES serializer. self.app.current_version.features.update(has_apps=True, has_nfc=True) self.reindex(Webapp) feature_profile = FeatureProfile(apps=False, nfc=True, mobileid=True) self.request = RequestFactory().get( '/?dev=firefoxos&pro=%s' % feature_profile.to_signature()) self.request.REGION = mkt.regions.USA self.request.user = self.profile res = self.serialize() eq_(res['feature_compatibility'], None)
class TestLoadFeatureProfile(mkt.site.tests.TestCase): def setUp(self): super(TestLoadFeatureProfile, self).setUp() self.profile = FeatureProfile(apps=True) self.signature = self.profile.to_signature() def test_does_nothing_on_desktop(self): request = RequestFactory().get('/?dev=desktop&pro=%s' % self.signature) load_feature_profile(request) eq_(request.feature_profile, None) def test_does_nothing_without_dev_param(self): request = RequestFactory().get('/?pro=%s' % self.signature) load_feature_profile(request) eq_(request.feature_profile, None) request = RequestFactory().get('/?device=mobilepro=%s' % self.signature) load_feature_profile(request) eq_(request.feature_profile, None) def test_does_nothing_without_profile_signature(self): request = RequestFactory().get('/?dev=firefoxos') load_feature_profile(request) eq_(request.feature_profile, None) def test_does_nothing_if_invalid_profile_signature_is_passed(self): request = RequestFactory().get('/?dev=firefoxos&pro=whatever') load_feature_profile(request) eq_(request.feature_profile, None) def test_works(self): request = RequestFactory().get('/?dev=firefoxos&pro=%s' % self.signature) load_feature_profile(request) eq_(request.feature_profile.to_list(), self.profile.to_list()) @mock.patch('mkt.features.utils.FeatureProfile.from_signature') def test_caching_on_request_property(self, from_signature_mock): fake_feature_profile = object() from_signature_mock.return_value = fake_feature_profile request = RequestFactory().get('/?dev=firefoxos&pro=%s' % self.signature) load_feature_profile(request) eq_(request.feature_profile, fake_feature_profile) from_signature_mock.return_value = None load_feature_profile(request) # Should not be None thanks to the property caching. eq_(request.feature_profile, fake_feature_profile)
class TestLoadFeatureProfile(mkt.site.tests.TestCase): def setUp(self): super(TestLoadFeatureProfile, self).setUp() self.profile = FeatureProfile(apps=True) self.signature = self.profile.to_signature() def test_does_nothing_on_desktop(self): request = RequestFactory().get('/?dev=desktop&pro=%s' % self.signature) load_feature_profile(request) eq_(request.feature_profile, None) def test_does_nothing_without_dev_param(self): request = RequestFactory().get('/?pro=%s' % self.signature) load_feature_profile(request) eq_(request.feature_profile, None) request = RequestFactory().get( '/?device=mobilepro=%s' % self.signature) load_feature_profile(request) eq_(request.feature_profile, None) def test_does_nothing_without_profile_signature(self): request = RequestFactory().get('/?dev=firefoxos') load_feature_profile(request) eq_(request.feature_profile, None) def test_does_nothing_if_invalid_profile_signature_is_passed(self): request = RequestFactory().get('/?dev=firefoxos&pro=whatever') load_feature_profile(request) eq_(request.feature_profile, None) def test_works(self): request = RequestFactory().get( '/?dev=firefoxos&pro=%s' % self.signature) load_feature_profile(request) eq_(request.feature_profile.to_list(), self.profile.to_list()) @mock.patch('mkt.features.utils.FeatureProfile.from_signature') def test_caching_on_request_property(self, from_signature_mock): fake_feature_profile = object() from_signature_mock.return_value = fake_feature_profile request = RequestFactory().get( '/?dev=firefoxos&pro=%s' % self.signature) load_feature_profile(request) eq_(request.feature_profile, fake_feature_profile) from_signature_mock.return_value = None load_feature_profile(request) # Should not be None thanks to the property caching. eq_(request.feature_profile, fake_feature_profile)
def get_feature_profile(self, request): profile = None if request.GET.get("dev") in ("firefoxos", "android"): sig = request.GET.get("pro") if sig: profile = FeatureProfile.from_signature(sig) return profile
def _test_kwargs(self, prefix): profile = FeatureProfile.from_int(self.features) kwargs = profile.to_kwargs(prefix=prefix) ok_(all([k.startswith(prefix) for k in kwargs.keys()])) eq_(kwargs.values().count(False), bin(self.features)[2:].count('0')) eq_(len(kwargs.values()), len(APP_FEATURES) - len(self.truths))
def get_feature_profile(self, request): profile = None if request.GET.get('dev') in ('firefoxos', 'android'): sig = request.GET.get('pro') if sig: profile = FeatureProfile.from_signature(sig) return profile
def test_from_list(self): bools = [False] * MOCK_APP_FEATURES_LIMIT bools[0] = True # apps bools[4] = True # light events bools[15] = True # proximity bools[19] = True # vibrate profile = FeatureProfile.from_list(bools) self._test_profile(profile)
def setUp(self): self.collection = Collection.objects.create(**self.collection_data) self.app = amo.tests.app_factory() self.collection.add_app(self.app) self.field = CollectionMembershipField() self.membership = CollectionMembership.objects.all()[0] self.request = RequestFactory() self.profile = FeatureProfile(apps=True).to_signature()
def get(self, request, *args, **kwargs): if 'pro' in request.GET: self.profile = FeatureProfile.from_signature(request.GET['pro']) else: self.profile = None features = OrderedDict(self._feature(i, slug) for i, slug in enumerate(APP_FEATURES.keys())) return Response(features, status=status.HTTP_200_OK)
def get(self, request, *args, **kwargs): if 'pro' in request.GET: self.profile = FeatureProfile.from_signature(request.GET['pro']) else: self.profile = None features = OrderedDict( self._feature(i, slug) for i, slug in enumerate(APP_FEATURES.keys())) return Response(features, status=status.HTTP_200_OK)
def _test_kwargs(self, prefix, only_true): profile = FeatureProfile.from_binary(self.binary) kwargs = profile.to_kwargs(prefix=prefix, only_true=only_true) ok_(all([k.startswith(prefix) for k in kwargs.keys()])) eq_(kwargs.values().count(True), self.binary.count('1')) if only_true: eq_(kwargs.values().count(False), 0) else: eq_(kwargs.values().count(False), self.binary.count('0'))
def setUp(self): self.collection = Collection.objects.create(**self.collection_data) self.app = amo.tests.app_factory() self.app.addondevicetype_set.get_or_create( device_type=amo.DEVICE_GAIA.id) self.collection.add_app(self.app, order=1) self.field = CollectionMembershipField() self.field.context = {} self.membership = CollectionMembership.objects.all()[0] self.profile = FeatureProfile(apps=True).to_signature()
def get_feature_profile(request): profile = None if request.GET.get('dev') in ('firefoxos', 'android'): sig = request.GET.get('pro') if sig: try: profile = FeatureProfile.from_signature(sig) except ValueError: pass return profile
def test_all_good_features_with_category(self): """Enable app features so they exactly match our device profile.""" fp = FeatureProfile.from_signature(self.profile) self.app.current_version.features.update(**dict(("has_%s" % k, v) for k, v in fp.items())) self.reindex(Webapp, "webapp") res = self.client.get(self.list_url + (self.qs,)) eq_(res.status_code, 200) eq_(len(res.json["featured"]), 1) eq_(int(res.json["featured"][0]["id"]), self.app.pk)
def setUp(self): self.client = RestOAuthClient(None) self.url = reverse('search-api') self.webapp = Webapp.objects.get(pk=337141) self.category = Category.objects.create(name='test', type=amo.ADDON_WEBAPP) # Pick a few common device features. self.profile = FeatureProfile(apps=True, audio=True, fullscreen=True, geolocation=True, indexeddb=True, sms=True).to_signature() self.qs = {'q': 'something', 'pro': self.profile, 'dev': 'firefoxos'}
def setUp(self): super(BaseFeaturedTests, self).setUp() self.cat = Category.objects.create(type=amo.ADDON_WEBAPP, slug='shiny') self.app = Webapp.objects.get(pk=337141) AddonDeviceType.objects.create( addon=self.app, device_type=DEVICE_CHOICES_IDS['firefoxos']) AddonCategory.objects.get_or_create(addon=self.app, category=self.cat) self.profile = FeatureProfile(apps=True, audio=True, fullscreen=True, geolocation=True, indexeddb=True, sms=True).to_signature() self.qs = {'cat': 'shiny', 'pro': self.profile, 'dev': 'firefoxos'}
def device_queue_search(request): """ Returns a queryset that can be used as a base for searching the device specific queue. """ filters = {"type": amo.ADDON_WEBAPP, "status": amo.STATUS_PENDING, "disabled_by_user": False} sig = request.GET.get("pro") if sig: profile = FeatureProfile.from_signature(sig) filters.update(dict(**profile.to_kwargs(prefix="_current_version__features__has_"))) return Webapp.version_and_file_transformer(Webapp.objects.filter(**filters))
def setUp(self): super(TestFeaturedNoCategories, self).setUp(api_name='fireplace') self.create_switch('buchets') self.cat = Category.objects.create(type=amo.ADDON_WEBAPP, slug='shiny') self.app = Webapp.objects.get(pk=337141) AddonCategory.objects.get_or_create(addon=self.app, category=self.cat) self.make_featured(app=self.app, category=None, region=mkt.regions.US) self.profile = FeatureProfile(apps=True, audio=True, fullscreen=True, geolocation=True, indexeddb=True, sms=True).to_signature() self.qs = {'pro': self.profile, 'dev': 'firefoxos'}
def test_all_good_features_with_category(self): """Enable app features so they exactly match our device profile.""" fp = FeatureProfile.from_signature(self.profile) self.app.current_version.features.update(**dict( ('has_%s' % k, v) for k, v in fp.items())) self.reindex(Webapp, 'webapp') res = self.client.get(self.list_url + (self.qs, )) eq_(res.status_code, 200) eq_(len(res.json['featured']), 1) eq_(int(res.json['featured'][0]['id']), self.app.pk)
def test_all_good_features(self): # Enable app features so they exactly match our device profile. fp = FeatureProfile.from_signature(self.profile) self.webapp.current_version.features.update(**dict(("has_%s" % k, v) for k, v in fp.items())) self.webapp.save() self.refresh("webapp") res = self.client.get(self.url + (self.qs,)) eq_(res.status_code, 200) obj = json.loads(res.content)["objects"][0] eq_(obj["slug"], self.webapp.app_slug)
def get_feature_profile(request): profile = None platforms = ('firefoxos', 'android') if (request.GET.get('dev') in platforms or request.GET.get('platform') in platforms): sig = request.GET.get('pro') if sig: try: profile = FeatureProfile.from_signature(sig) except ValueError: pass return profile
def test_all_good_features(self): # Enable app features so they exactly match our device profile. fp = FeatureProfile.from_signature(self.features) self.webapp.current_version.features.update( **dict(('has_%s' % k, v) for k, v in fp.items())) self.webapp.save() self.refresh('webapp') res = self.client.get(self.url, data=self.qs) eq_(res.status_code, 200) obj = json.loads(res.content)['objects'][0] eq_(obj['slug'], self.webapp.app_slug)
def test_all_good_features(self): # Enable app features so they exactly match our device profile. fp = FeatureProfile.from_signature(self.profile) self.webapp.current_version.features.update(**dict( ('has_%s' % k, v) for k, v in fp.items())) self.webapp.save() self.refresh('webapp') res = self.client.get(self.url + (self.qs, )) eq_(res.status_code, 200) obj = json.loads(res.content)['objects'][0] eq_(obj['slug'], self.webapp.app_slug)
def setUp(self): self.client = RestOAuthClient(None) self.url = reverse('search-api') self.webapp = Webapp.objects.get(pk=337141) self.webapp.addondevicetype_set.create(device_type=amo.DEVICE_GAIA.id) # Pick a few common device features. self.profile = FeatureProfile(apps=True, audio=True, fullscreen=True, geolocation=True, indexeddb=True, sms=True).to_signature() self.qs = {'q': 'something', 'pro': self.profile, 'dev': 'firefoxos'}
def test_no_feature_profile_filtering(self): feature_profile = FeatureProfile().to_signature() qs = {'q': 'something', 'pro': feature_profile, 'dev': 'firefoxos'} # Enable an app feature that doesn't match one in our profile. self.webapp.current_version.features.update(has_pay=True) self.webapp.save() self.refresh('webapp') res = self.client.get(self.url, qs) eq_(res.status_code, 200) eq_(len(res.json['objects']), 1) obj = res.json['objects'][0] eq_(obj['slug'], self.webapp.app_slug)
def setUp(self): super(BaseFeaturedTests, self).setUp() self.cat = 'books' self.app = Webapp.objects.get(pk=337141) AddonDeviceType.objects.create( addon=self.app, device_type=DEVICE_CHOICES_IDS['firefoxos']) self.app.update(categories=[self.cat]) self.profile = FeatureProfile(apps=True, audio=True, fullscreen=True, geolocation=True, indexeddb=True, sms=True).to_signature() self.qs = {'cat': self.cat, 'pro': self.profile, 'dev': 'firefoxos'}
def field_to_native(self, obj, field_name): value = get_component(obj, self.source) # Filter apps based on feature profiles. if hasattr(self, 'context') and 'request' in self.context: sig = self.context['request'].GET.get('pro') if sig: try: profile = FeatureProfile.from_signature(sig) except ValueError: pass else: value = value.filter(**profile.to_kwargs( prefix='app___current_version__features__has_')) return [self.to_native(item) for item in value.all()]
def device_queue_search(request): """ Returns a queryset that can be used as a base for searching the device specific queue. """ filters = { 'status': amo.STATUS_PENDING, 'disabled_by_user': False, } sig = request.GET.get('pro') if sig: profile = FeatureProfile.from_signature(sig) filters.update(dict( **profile.to_kwargs(prefix='_latest_version__features__has_') )) return Webapp.version_and_file_transformer( Webapp.objects.filter(**filters))
def load_feature_profile(request): """ Adds a `feature_profile` on the request object if one is present and the dev parameter is either firefoxos or android. Does nothing if one was already set. """ if hasattr(request, 'feature_profile'): return profile = None if request.GET.get('dev') in ('firefoxos', 'android'): sig = request.GET.get('pro') if sig: try: profile = FeatureProfile.from_signature(sig) except ValueError: pass request.feature_profile = profile
def alter_list_data_to_serialize(self, request, data): form_data = self.search_form(request) region = getattr(request, 'REGION', mkt.regions.WORLDWIDE) if form_data['cat']: category = Category.objects.get(pk=form_data['cat']) else: category = None # Filter by device feature profile. profile = None if request.GET.get('dev') in ('firefoxos', 'android'): sig = request.GET.get('pro') if sig: profile = FeatureProfile.from_signature(sig) qs = Webapp.featured(cat=category, region=region, profile=profile) bundles = [self.build_bundle(obj=obj, request=request) for obj in qs] data['featured'] = [AppResource().full_dehydrate(bundle) for bundle in bundles] return data
def alter_list_data_to_serialize(self, request, data): form_data = self.search_form(request) region = getattr(request, 'REGION', mkt.regions.WORLDWIDE) cat_slug = form_data.get('cat') if cat_slug: cat_slug = [cat_slug] # Filter by device feature profile. profile = None if request.GET.get('dev') in ('firefoxos', 'android'): sig = request.GET.get('pro') if sig: profile = FeatureProfile.from_signature(sig) qs = Webapp.featured(cat=cat_slug, region=region, profile=profile) bundles = [self.build_bundle(obj=obj, request=request) for obj in qs] data['featured'] = [AppResource().full_dehydrate(bundle) for bundle in bundles] # Alter the _view_name so that statsd logs seperately from search. request._view_name = 'featured' return data
def alter_list_data_to_serialize(self, request, data): form_data = self.search_form(request) region = getattr(request, 'REGION', mkt.regions.WORLDWIDE) if form_data['cat']: category = Category.objects.get(pk=form_data['cat']) else: category = None # Filter by device feature profile. profile = None if request.GET.get('dev') in ('firefoxos', 'android'): sig = request.GET.get('pro') if sig: profile = FeatureProfile.from_signature(sig) qs = Webapp.featured(cat=category, region=region, profile=profile) bundles = [self.build_bundle(obj=obj, request=request) for obj in qs] data['featured'] = [ AppResource().full_dehydrate(bundle) for bundle in bundles ] return data
def test_from_int(self): profile = FeatureProfile.from_int(self.features) self._test_profile(profile)
def to_native(self, obj): ret = super(AppFeaturesSerializer, self).to_native(obj) profile = FeatureProfile.from_signature(obj.to_signature()) ret['required'] = profile.to_list() return ret
def test_from_int_limit(self): profile = FeatureProfile.from_int( self.features, limit=MOCK_APP_FEATURES_LIMIT) self._test_profile_values(profile)
def test_from_signature(self): profile = FeatureProfile.from_signature(self.signature) self._test_profile(profile)
def test_init(self): profile = FeatureProfile(**dict( (f, True) for f in self.expected_features)) eq_(profile.to_signature(), self.signature) eq_(profile.to_int(), self.features)
def setUp(self): super(TestLoadFeatureProfile, self).setUp() self.profile = FeatureProfile(apps=True) self.signature = self.profile.to_signature()
def test_init(self): profile = FeatureProfile(**dict((f, True) for f in self.truths)) eq_(profile.to_signature(), self.signature) eq_(profile.to_int(), self.features)
def test_from_binary(self): profile = FeatureProfile.from_binary(self.binary) self._test_profile(profile)
def get_list(self, request=None, **kwargs): form_data = self.search_form(request) is_admin = acl.action_allowed(request, 'Admin', '%') is_reviewer = acl.action_allowed(request, 'Apps', 'Review') uses_es = waffle.switch_is_active('search-api-es') # Pluck out status and addon type first since it forms part of the base # query, but only for privileged users. status = form_data['status'] addon_type = form_data['type'] base_filters = { 'type': addon_type, } # Allow reviewers and admins to search by statuses other than PUBLIC. if status and (status == 'any' or status != amo.STATUS_PUBLIC): if is_admin or is_reviewer: base_filters['status'] = status else: return http.HttpUnauthorized( content=json.dumps( {'reason': _('Unauthorized to filter by status.')})) # Filter by device feature profile. profile = None # TODO: Remove uses_es conditional with 'search-api-es' waffle. if uses_es and request.GET.get('dev') in ('firefoxos', 'android'): sig = request.GET.get('pro') if sig: profile = FeatureProfile.from_signature(sig) # Filter by region. region = getattr(request, 'REGION', mkt.regions.WORLDWIDE) qs = _get_query(region, gaia=request.GAIA, mobile=request.MOBILE, tablet=request.TABLET, filters=base_filters, new_idx=True) qs = _filter_search(request, qs, form_data, region=region, profile=profile) paginator = self._meta.paginator_class(request.GET, qs, resource_uri=self.get_resource_list_uri(), limit=self._meta.limit) page = paginator.page() # Rehydrate the results as per tastypie. objs = [] for obj in page['objects']: obj.pk = obj.id objs.append(self.build_bundle(obj=obj, request=request)) if uses_es: page['objects'] = [self.full_dehydrate(bundle) for bundle in objs] else: page['objects'] = [AppResource().full_dehydrate(bundle) for bundle in objs] # This isn't as quite a full as a full TastyPie meta object, # but at least it's namespaced that way and ready to expand. to_be_serialized = self.alter_list_data_to_serialize(request, page) return self.create_response(request, to_be_serialized)