Example #1
0
    def test_update_counts_from_file_includes_disabled_addons(self):
        addon_factory(
            guid='{39e6cf40-02f6-4bda-b1ee-409910ffd9f9}',
            slug='disabled-addon',
            status=amo.STATUS_DISABLED)
        addon_factory(
            guid='9c444b87-1124-4fd2-b97f-8fb7e9be1820',
            slug='incomplete-addon', status=amo.STATUS_NULL)

        management.call_command('update_counts_from_file', hive_folder,
                                date=self.date, stats_source=self.stats_source)
        assert UpdateCount.objects.all().count() == 2

        update_count = UpdateCount.objects.get(addon_id=3615)
        # should be identical to `statuses.userEnabled`
        assert update_count.count == 4
        assert update_count.date == date(2014, 7, 10)
        assert update_count.versions == {u'3.8': 2, u'3.7': 3}
        assert update_count.statuses == {u'userDisabled': 1, u'userEnabled': 4}

        update_count = UpdateCount.objects.get(addon__slug='disabled-addon')
        assert update_count.count == 2
        assert update_count.date == date(2014, 7, 10)
        assert update_count.versions == {}
        assert update_count.statuses == {u'userEnabled': 2}

        # Make sure we didn't generate any stats for incomplete add-ons
        assert not UpdateCount.objects.filter(
            addon__slug='incomplete-addon').exists()
Example #2
0
    def test_recommendations(self):
        author = user_factory()
        recommendations = {
            101: addon_factory(id=101, guid='101@mozilla', users=[author]),
            102: addon_factory(id=102, guid='102@mozilla', users=[author]),
            103: addon_factory(id=103, guid='103@mozilla', users=[author]),
            104: addon_factory(id=104, guid='104@mozilla', users=[author]),
        }
        replacement_items = [
            DiscoItem(addon_id=101, is_recommendation=True),
            DiscoItem(addon_id=102, is_recommendation=True),
            DiscoItem(addon_id=103, is_recommendation=True),
            DiscoItem(addon_id=104, is_recommendation=True),
        ]
        self.addons.update(recommendations)
        self.get_recommendations.return_value = replacement_items

        response = self.client.get(self.url, {'lang': 'en-US',
                                              'telemetry-client-id': '666'})
        # should still be the same number of results.
        assert response.data['count'] == len(discopane_items)
        assert response.data['results']

        # personas aren't replaced by recommendations, so should be as before.
        new_discopane_items = replace_extensions(
            discopane_items, replacement_items)
        for i, result in enumerate(response.data['results']):
            if 'theme_data' in result['addon']:
                self._check_disco_theme(result, new_discopane_items[i])
                # There aren't any theme recommendations.
                assert result['is_recommendation'] is False
            else:
                self._check_disco_addon(result, new_discopane_items[i])
                assert result['is_recommendation'] is True
Example #3
0
 def setUpTestData(cls):
     cls.addon1 = addon_factory(guid='@guid1')
     cls.addon2 = addon_factory(guid='@guid2')
     cls.addon3 = addon_factory(guid='@guid3')
     cls.user = user_factory()
     grant_permission(cls.user, 'Admin:Tools', 'Admin Group')
     grant_permission(cls.user, 'AbuseReports:Edit', 'Abuse Report Triage')
     # Create a few abuse reports.
     AbuseReport.objects.create(
         addon=cls.addon1, guid='@guid1', message='Foo',
         state=AbuseReport.STATES.VALID,
         created=days_ago(98))
     AbuseReport.objects.create(
         addon=cls.addon2, guid='@guid2', message='Bar',
         state=AbuseReport.STATES.VALID)
     AbuseReport.objects.create(
         addon=cls.addon3, guid='@guid3', message='Soap',
         reason=AbuseReport.REASONS.OTHER,
         created=days_ago(100))
     AbuseReport.objects.create(
         addon=cls.addon1, guid='@guid1', message='',
         reporter=user_factory())
     # This is a report for an addon not in the database.
     AbuseReport.objects.create(
         guid='@unknown_guid', addon_name='Mysterious Addon', message='Doo')
     # This is one against a user.
     AbuseReport.objects.create(
         user=user_factory(), message='Eheheheh')
Example #4
0
 def setUp(self):
     user_factory(
         id=settings.TASK_USER_ID, username='******',
         email='*****@*****.**')
     self.addons = [
         addon_factory(average_daily_users=666, users=[user_factory()]),
         addon_factory(average_daily_users=999, users=[user_factory()]),
     ]
     self.versions = [
         version_factory(
             addon=self.addons[0], file_kw={
                 'status': amo.STATUS_AWAITING_REVIEW,
                 'is_webextension': True}),
         version_factory(
             addon=self.addons[1], file_kw={
                 'status': amo.STATUS_AWAITING_REVIEW,
                 'is_webextension': True}),
     ]
     self.files = [
         self.versions[0].all_files[0],
         self.versions[1].all_files[0],
     ]
     self.versions[0].update(nomination=days_ago(1))
     FileValidation.objects.create(
         file=self.versions[0].all_files[0], validation=u'{}')
     FileValidation.objects.create(
         file=self.versions[1].all_files[0], validation=u'{}')
     super(TestAutoApproveCommandTransactions, self).setUp()
Example #5
0
    def test_fix_langpack_summary(self):
        """What happened on our production system:

        The `zadmin.tasks.fetch_langpack` task set `summary` to the
        same translation instance of `name` for add-ons without a
        summary set.

        This meant that changing `name` or `summary` automatically
        changed the other one.
        """
        owner = UserProfile.objects.get(email=settings.LANGPACK_OWNER_EMAIL)
        a1 = addon_factory(name='addon 1', users=[owner])
        a1.summary = a1.name
        a1.save()

        # We won't touch this add-on, wrong owner
        a2 = addon_factory(name='addon 2', users=[owner])
        a2.summary = a2.name
        a2.save()

        assert a1.summary.id == a1.name.id
        assert a2.summary.id == a2.summary.id

        # Now, let's fix this mess.
        management.call_command('fix_langpack_summary')

        a1.refresh_from_db()
        a2.refresh_from_db()

        assert a1.summary_id != a1.name_id

        # Didn't touch wrong owner add-on
        assert a2.summary_id == a2.summary_id
Example #6
0
    def test_count_stats_for_date(self):
        # Add a listed add-on, it should show up in "addon_count_new".
        listed_addon = addon_factory()

        # Add an unlisted version to that add-on, it should *not* increase the
        # "version_count_new" count.
        version_factory(
            addon=listed_addon, channel=amo.RELEASE_CHANNEL_UNLISTED)

        # Add an unlisted add-on, it should not show up in either
        # "addon_count_new" or "version_count_new".
        addon_factory(version_kw={
            'channel': amo.RELEASE_CHANNEL_UNLISTED
        })

        date = datetime.date.today()
        job = 'addon_count_new'
        tasks.update_global_totals(job, date)
        global_stat = GlobalStat.objects.no_cache().get(date=date, name=job)
        assert global_stat.count == 1

        job = 'version_count_new'
        tasks.update_global_totals(job, date)
        global_stat = GlobalStat.objects.no_cache().get(date=date, name=job)
        assert global_stat.count == 1
Example #7
0
    def test_through_cron(self):
        # Yesterday, create some stuff.
        with freeze_time(datetime.datetime.now() - datetime.timedelta(days=1)):
            yesterday = datetime.date.today()

            # Add a listed add-on, it should show up in "addon_count_new".
            listed_addon = addon_factory(created=datetime.datetime.now())

            # Add an unlisted version to that add-on, it should *not* increase
            # the "version_count_new" count.
            version_factory(
                addon=listed_addon, channel=amo.RELEASE_CHANNEL_UNLISTED)

            # Add an unlisted add-on, it should not show up in either
            # "addon_count_new" or "version_count_new".
            addon_factory(version_kw={
                'channel': amo.RELEASE_CHANNEL_UNLISTED
            })

        # Launch the cron.
        cron.update_global_totals()

        job = 'addon_count_new'
        global_stat = GlobalStat.objects.get(date=yesterday, name=job)
        assert global_stat.count == 1

        job = 'version_count_new'
        global_stat = GlobalStat.objects.get(date=yesterday, name=job)
        assert global_stat.count == 1
    def create_named_addon_with_author(self, name, author=None):
        """Create a generic addon and a user.

        The user will be created if a user is not given.

        """

        if author is None:
            author = user_factory()
        try:
            generate_user(author)
        except Exception:  # django.db.utils.IntegrityError
            # If the user is already made, use that same user,
            # if not use created user
            addon = addon_factory(
                status=STATUS_PUBLIC,
                users=[UserProfile.objects.get(username=author)],
                name=u'{}'.format(name),
                slug=u'{}'.format(name),
            )
            addon.save()
        else:
            addon = addon_factory(
                status=STATUS_PUBLIC,
                users=[UserProfile.objects.get(username=author.username)],
                name=u'{}'.format(name),
                slug=u'{}'.format(name),
            )
            addon.save()
        return addon
    def test_only_show_notifications_user_has_permission_to(self):
        create_switch('activate-basket-sync')

        with patch('basket.base.request', autospec=True) as request_call:
            request_call.return_value = {
                'status': 'ok', 'token': '123', 'newsletters': []}

            form = UserEditForm({}, instance=self.user)

        request_call.assert_called_with(
            'get', 'lookup-user',
            headers={'x-api-key': 'testkey'},
            params={'email': u'*****@*****.**'})

        # It needs a developer account to subscribe to a newsletter
        # So the `announcements` notification is not among the valid choices
        # This isn't really user visible since the user doesn't have
        # the ability to choose newsletters he doesn't have permissions
        # to see.
        assert len(form.fields['notifications'].choices) == 2
        assert form.fields['notifications'].choices[0][0] == 3
        assert form.fields['notifications'].choices[1][0] == 4

        addon_factory(users=[self.user])

        # Clear cache
        del self.user.is_developer

        form = UserEditForm({}, instance=self.user)
        assert len(form.fields['notifications'].choices) == 10
        assert [x[0] for x in form.fields['notifications'].choices] == [
            3, 4, 5, 6, 7, 9, 10, 11, 12, 8
        ]
Example #10
0
    def test_pagination(self):
        addon = addon_factory(slug='my-addon', name=u'My Addôn',
                              weekly_downloads=33)
        addon2 = addon_factory(slug='my-second-addon', name=u'My second Addôn',
                               weekly_downloads=22)
        addon_factory(slug='my-third-addon', name=u'My third Addôn',
                      weekly_downloads=11)
        self.refresh()

        data = self.perform_search_with_senior_editor(
            self.url, {'page_size': 1})
        assert data['count'] == 3
        assert len(data['results']) == 1

        result = data['results'][0]
        assert result['id'] == addon.pk
        assert result['name'] == {'en-US': u'My Addôn'}
        assert result['slug'] == 'my-addon'

        # Search using the second page URL given in return value.
        # Expect 0 SQL queries since they should be cached after the first
        # call above.
        data = self.perform_search_with_senior_editor(
            data['next'], expected_queries_count=0)
        assert data['count'] == 3
        assert len(data['results']) == 1

        result = data['results'][0]
        assert result['id'] == addon2.pk
        assert result['name'] == {'en-US': u'My second Addôn'}
        assert result['slug'] == 'my-second-addon'
Example #11
0
    def test_can_change_addon_with_discovery_edit_permission(self):
        addon = addon_factory(name=u'BarFöo')
        addon2 = addon_factory(name=u'Another ône', slug='another-addon')
        item = DiscoveryItem.objects.create(addon=addon)
        self.detail_url = reverse(
            'admin:discovery_discoveryitem_change', args=(item.pk,)
        )
        user = user_factory()
        self.grant_permission(user, 'Admin:Tools')
        self.grant_permission(user, 'Discovery:Edit')
        self.client.login(email=user.email)
        response = self.client.get(self.detail_url, follow=True)
        assert response.status_code == 200
        assert u'BarFöo' in response.content.decode('utf-8')

        # Change add-on using the slug.
        response = self.client.post(
            self.detail_url,
            {'addon': six.text_type(addon2.slug)}, follow=True)
        assert response.status_code == 200
        item.reload()
        assert DiscoveryItem.objects.count() == 1
        # assert item.addon == addon2

        # Change add-on using the id.
        response = self.client.post(
            self.detail_url, {'addon': six.text_type(addon.pk)}, follow=True)
        assert response.status_code == 200
        item.reload()
        assert DiscoveryItem.objects.count() == 1
        assert item.addon == addon
Example #12
0
    def test_basic(self):
        addon = addon_factory(
            name=u'My Addôn', slug='my-addon', status=amo.STATUS_NULL,
            version_kw={'channel': amo.RELEASE_CHANNEL_UNLISTED},
            weekly_downloads=666)
        addon2 = addon_factory(slug='my-second-addon', name=u'My second Addôn',
                               weekly_downloads=555)
        addon2.delete()
        self.refresh()

        data = self.perform_search_with_senior_editor(self.url)  # No query.
        assert data['count'] == 2
        assert len(data['results']) == 2

        result = data['results'][0]
        assert result['id'] == addon.pk
        assert result['status'] == 'incomplete'
        assert result['name'] == {'en-US': u'My Addôn'}
        assert result['slug'] == 'my-addon'
        assert result['last_updated'] == addon.last_updated.isoformat() + 'Z'
        assert result['latest_unlisted_version']
        assert (result['latest_unlisted_version']['id'] ==
                addon.latest_unlisted_version.pk)

        result = data['results'][1]
        assert result['id'] == addon2.pk
        assert result['name'] == {'en-US': u'My second Addôn'}
        assert result['slug'] is None  # Because it was deleted.
        assert result['status'] == 'deleted'
        assert result['latest_unlisted_version'] is None
    def test_only_affects_legacy_addons_targeting_firefox_lower_than_56(self):
        # Should be included:
        addon = addon_factory(version_kw={'max_app_version': '55.*'})
        addon2 = addon_factory(version_kw={'application': amo.ANDROID.id})
        addon3 = addon_factory(type=amo.ADDON_THEME)
        # Should not be included:
        addon_factory(file_kw={'is_webextension': True})
        addon_factory(version_kw={'max_app_version': '56.*'})
        addon_factory(version_kw={'application': amo.THUNDERBIRD.id})
        # Also should not be included, this super weird add-on targets both
        # Firefox and Thunderbird - with a low version for Thunderbird, but a
        # high enough (56.*) for Firefox to be ignored by the task.
        weird_addon = addon_factory(
            version_kw={'application': amo.THUNDERBIRD.id})
        av_min, _ = AppVersion.objects.get_or_create(
            application=amo.FIREFOX.id, version='48.*')
        ApplicationsVersions.objects.get_or_create(
            application=amo.FIREFOX.id, version=weird_addon.current_version,
            min=av_min, max=self.firefox_56_star)

        with count_subtask_calls(pa.bump_appver_for_legacy_addons) as calls:
            call_command(
                'process_addons', task='bump_appver_for_legacy_addons')

        assert len(calls) == 1
        assert calls[0]['kwargs']['args'] == [[addon.pk, addon2.pk, addon3.pk]]
Example #14
0
 def test_valid_addon(self):
     addon_factory(slug='bar')
     form = ReplacementAddonAdmin(
         ReplacementAddon, admin.site).get_form(None)(
             {'guid': 'foo', 'path': '/addon/bar/'})
     assert form.is_valid(), form.errors
     assert form.cleaned_data['path'] == '/addon/bar/'
Example #15
0
def test_get_disco_recommendations(call_recommendation_server):
    expected_addons = [
        addon_factory(guid='101@mozilla'),
        addon_factory(guid='102@mozilla'),
        addon_factory(guid='103@mozilla'),
        addon_factory(guid='104@mozilla'),
    ]
    # Only the first one has a DiscoveryItem. The rest should still be
    # returned.

    call_recommendation_server.return_value = [
        '101@mozilla', '102@mozilla', '103@mozilla', '104@mozilla'
    ]
    recommendations = get_disco_recommendations('0', [])
    call_recommendation_server.assert_called_with(
        'https://taar.dev.mozaws.net/v1/api/recommendations/', '0', None,
        verb='post')
    assert [result.addon for result in recommendations] == expected_addons

    # only valid, public add-ons should match guids
    incomplete_addon = expected_addons.pop()
    incomplete_addon.update(status=amo.STATUS_NULL)
    # Remove this one and have recommendations return a bad guid instead.
    expected_addons.pop()
    call_recommendation_server.return_value = [
        '101@mozilla', '102@mozilla', '103@badbadguid', '104@mozilla'
    ]
    recommendations = get_disco_recommendations('0', [])
    assert [result.addon for result in recommendations] == expected_addons
Example #16
0
    def test_basic(self):
        addon = addon_factory(slug='my-addon', name=u'My Addôn',
                              weekly_downloads=666, is_listed=False)
        addon2 = addon_factory(slug='my-second-addon', name=u'My second Addôn',
                               weekly_downloads=555)
        addon2.delete()
        self.refresh()

        data = self.perform_search_with_senior_editor(self.url)  # No query.
        assert data['count'] == 2
        assert len(data['results']) == 2

        result = data['results'][0]
        assert result['id'] == addon.pk
        assert result['is_listed'] is False
        assert result['status'] == 'public'
        assert result['name'] == {'en-US': u'My Addôn'}
        assert result['slug'] == 'my-addon'
        assert result['last_updated'] == addon.last_updated.isoformat()

        result = data['results'][1]
        assert result['id'] == addon2.pk
        assert result['name'] == {'en-US': u'My second Addôn'}
        assert result['slug'] is None  # Because it was deleted.
        assert result['status'] == 'deleted'
Example #17
0
    def setUp(self):
        super(TestDiscoveryRecommendations, self).setUp()

        self.addons = []

        # This one should not appear anywhere, position isn't set.
        DiscoveryItem.objects.create(addon=addon_factory())

        for i in range(1, 8):
            if i % 3:
                type_ = amo.ADDON_PERSONA
            else:
                type_ = amo.ADDON_EXTENSION
            addon = addon_factory(type=type_)
            self.addons.append(addon)
            DiscoveryItem.objects.create(addon=addon, position=i)

        for i in range(1, 8):
            if i % 3:
                type_ = amo.ADDON_PERSONA
            else:
                type_ = amo.ADDON_EXTENSION
            addon = addon_factory(type=type_)
            DiscoveryItem.objects.create(addon=addon, position_china=i)

        patcher = mock.patch(
            'olympia.discovery.views.get_recommendations')
        self.get_recommendations = patcher.start()
        self.addCleanup(patcher.stop)
        # If no recommendations then results should be as before - tests from
        # the parent class check this.
        self.get_recommendations.return_value = []
        self.url = reverse_ns('discovery-list')
Example #18
0
    def test_response(self):
        lwt = addon_factory(type=amo.ADDON_PERSONA)
        lwt.persona.persona_id = 666
        lwt.persona.save()
        stheme = addon_factory(type=amo.ADDON_STATICTHEME)
        stheme.current_version.files.all()[0].update(
            filename='foo.xpi', hash='brown')
        MigratedLWT.objects.create(
            lightweight_theme=lwt, static_theme=stheme, getpersonas_id=666)
        update = self.get_update('en-US', lwt.id)

        response = json.loads(update.get_json())
        url = '{0}{1}/{2}?{3}'.format(
            user_media_url('addons'), str(stheme.id), 'foo.xpi',
            urllib.urlencode({'filehash': 'brown'}))
        assert update.data == {
            'stheme_id': stheme.id, 'filename': 'foo.xpi', 'hash': 'brown'}
        assert response == {
            "converted_theme": {
                "url": url,
                "hash": 'brown'
            }
        }

        update = self.get_update('en-US', 666, 'src=gp')
        response = json.loads(update.get_json())
        assert update.data == {
            'stheme_id': stheme.id, 'filename': 'foo.xpi', 'hash': 'brown'}
        assert response == {
            "converted_theme": {
                "url": url,
                "hash": 'brown'
            }
        }
def test_migrate_lwts_to_static_themes(add_static_theme_from_lwt_mock):
    persona_a = addon_factory(type=amo.ADDON_PERSONA, slug='theme_a')
    persona_b = addon_factory(type=amo.ADDON_PERSONA, slug='theme_b')
    addon_a = addon_factory(type=amo.ADDON_STATICTHEME)
    addon_b = addon_factory(type=amo.ADDON_STATICTHEME)
    add_static_theme_from_lwt_mock.side_effect = [addon_a, addon_b]

    # call the migration task, as the command would:
    migrate_lwts_to_static_themes([persona_a.id, persona_b.id])

    assert MigratedLWT.objects.all().count() == 2

    persona_a.reload()
    addon_a.reload()
    assert persona_a.status == amo.STATUS_DELETED
    assert MigratedLWT.objects.get(
        lightweight_theme=persona_a).static_theme == addon_a
    assert addon_a.slug == 'theme_a'

    persona_b.reload()
    addon_a.reload()
    assert persona_b.status == amo.STATUS_DELETED
    assert MigratedLWT.objects.get(
        lightweight_theme=persona_b).static_theme == addon_b
    assert addon_b.slug == 'theme_b'
Example #20
0
def test_repack_themes_for_69():
    user_factory(id=settings.TASK_USER_ID)
    broken_theme = addon_factory(name='broken')
    already_theme = addon_factory(name='already')
    deprecated_theme = addon_factory(
        name='deprecated', version_kw={'version': '1.0'})

    to_mock = 'olympia.addons.tasks.new_theme_version_with_69_properties'
    with mock.patch(to_mock) as new_theme_version_with_69_properties_mock:
        with mock.patch('olympia.addons.tasks.parse_addon') as parse_mock:
            parse_mock.configure_mock(side_effect=[
                IOError(),
                {'theme': {'colors': {'frame': '#baa'}}},
                {'theme': {'colors': {'accentcolor': '#f00'}}},
            ])
            # call the task, as the command would:
            repack_themes_for_69([
                broken_theme.id,
                already_theme.id,
                deprecated_theme.id,
            ])

        new_theme_version_with_69_properties_mock.assert_called_once()
        new_theme_version_with_69_properties_mock.assert_called_with(
            deprecated_theme.current_version)
Example #21
0
    def test_count_stats_for_date(self):
        # Add a listed add-on, it should show up in "addon_count_new".
        listed_addon = addon_factory(created=datetime.datetime.now())

        # Add an unlisted version to that add-on, it should *not* increase the
        # "version_count_new" count.
        version_factory(
            addon=listed_addon, channel=amo.RELEASE_CHANNEL_UNLISTED)

        # Add an unlisted add-on, it should not show up in either
        # "addon_count_new" or "version_count_new".
        addon_factory(version_kw={
            'channel': amo.RELEASE_CHANNEL_UNLISTED
        })

        date = datetime.date.today()
        job = 'addon_count_new'
        tasks.update_global_totals(job, date)
        global_stat = GlobalStat.objects.get(date=date, name=job)
        assert global_stat.count == 1

        # Should still work if the date is passed as a datetime string (what
        # celery serialization does).
        job = 'version_count_new'
        tasks.update_global_totals(job, datetime.datetime.now().isoformat())
        global_stat = GlobalStat.objects.get(date=date, name=job)
        assert global_stat.count == 1
Example #22
0
def test_recreate_theme_previews():
    xpi_path = os.path.join(
        settings.ROOT,
        'src/olympia/devhub/tests/addons/mozilla_static_theme.zip')

    addon_without_previews = addon_factory(type=amo.ADDON_STATICTHEME)
    copy_stored_file(
        xpi_path,
        addon_without_previews.current_version.all_files[0].file_path)
    addon_with_previews = addon_factory(type=amo.ADDON_STATICTHEME)
    copy_stored_file(
        xpi_path,
        addon_with_previews.current_version.all_files[0].file_path)
    VersionPreview.objects.create(
        version=addon_with_previews.current_version,
        sizes={'image': [123, 456], 'thumbnail': [34, 45]})

    assert addon_without_previews.current_previews.count() == 0
    assert addon_with_previews.current_previews.count() == 1
    recreate_theme_previews(
        [addon_without_previews.id, addon_with_previews.id])
    assert addon_without_previews.reload().current_previews.count() == 3
    assert addon_with_previews.reload().current_previews.count() == 3
    sizes = addon_without_previews.current_previews.values_list(
        'sizes', flat=True)
    assert list(sizes) == [
        {'image': list(amo.THEME_PREVIEW_SIZES['header']['full']),
         'thumbnail': list(amo.THEME_PREVIEW_SIZES['header']['thumbnail'])},
        {'image': list(amo.THEME_PREVIEW_SIZES['list']['full']),
         'thumbnail': list(amo.THEME_PREVIEW_SIZES['list']['thumbnail'])},
        {'image': list(amo.THEME_PREVIEW_SIZES['single']['full']),
         'thumbnail': list(amo.THEME_PREVIEW_SIZES['single']['thumbnail'])}]
Example #23
0
    def test_total_and_average_downloads(self):
        addon = Addon.objects.get(pk=3615)
        old_total_downloads = addon.total_downloads
        DownloadCount.objects.update_or_create(
            addon=addon, date=datetime.date.today(), defaults={'count': 42})
        DownloadCount.objects.update_or_create(
            addon=addon,
            date=datetime.date.today() - datetime.timedelta(days=1),
            defaults={'count': 59})

        addon_deleted = addon_factory()
        addon_deleted.delete()
        DownloadCount.objects.update_or_create(
            addon=addon_deleted,
            date=datetime.date.today(), defaults={'count': 666})

        addon2 = addon_factory()
        DownloadCount.objects.update_or_create(
            addon=addon2,
            date=datetime.date.today() - datetime.timedelta(days=366),
            defaults={'count': 21})

        addon_factory()  # No downloads for this add-on

        cron.update_addon_download_totals()

        addon.reload()
        assert addon.total_downloads != old_total_downloads
        assert addon.total_downloads == 101

        addon2.reload()
        assert addon2.total_downloads == 21
Example #24
0
    def test_add_static_theme_from_lwt(self):
        author = user_factory()
        persona = addon_factory(
            type=amo.ADDON_PERSONA, users=[author], name='Firefox Theme')
        persona.update(
            created=self.create_date, modified=self.modify_date,
            last_updated=self.update_date)
        persona.persona.license = licenses.LICENSE_CC_BY_ND.id
        Tag.objects.create(tag_text='themey').save_tag(persona)
        License.objects.create(builtin=licenses.LICENSE_CC_BY_ND.builtin)
        rating_user = user_factory()
        rating = Rating.objects.create(
            addon=persona, version=persona.current_version, user=rating_user,
            rating=2, body=u'fooooo', user_responsible=rating_user)
        ThemeUpdateCount.objects.create(
            addon_id=persona.id, date=datetime(2018, 1, 1), count=123)
        ThemeUpdateCount.objects.create(
            addon_id=persona.id, date=datetime(2018, 2, 1), count=456)
        # Create a count for an addon that shouldn't be migrated too.
        ThemeUpdateCount.objects.create(
            addon_id=addon_factory().id, date=datetime(2018, 2, 1), count=45)
        # And add it to a collection
        collection = collection_factory()
        collection.add_addon(persona)
        collection.add_addon(addon_factory())

        static_theme = add_static_theme_from_lwt(persona)

        self._check_result(
            static_theme, [author], list(persona.tags.all()),
            persona.all_categories, licenses.LICENSE_CC_BY_ND.builtin,
            [rating], collection)
Example #25
0
    def setUp(self):
        self.persona = addon_factory(type=amo.ADDON_PERSONA)
        self.extension = addon_factory()
        self.static_theme = addon_factory(type=amo.ADDON_STATICTHEME)
        self.awaiting_review = addon_factory(status=amo.STATUS_NOMINATED)

        today = datetime.date.today()

        stats = [
            (today - datetime.timedelta(days=days_in_past), update_count)
            for days_in_past, update_count in (
                (1, 827080), (2, 787930), (3, 995860), (4, 1044260),
                (5, 105431), (6, 106065), (7, 980930), (8, 817100), (9, 78843),
                (10, 993830), (11, 104431), (12, 105943), (13, 105039),
                (14, 100183), (15, 82265), (16, 100183), (17, 82265),
                (18, 100183), (19, 82265), (20, 100183), (21, 82265),

            )]

        for obj in (self.persona, self.extension, self.static_theme,
                    self.awaiting_review):
            UpdateCount.objects.bulk_create([
                UpdateCount(addon=obj, date=date, count=count)
                for date, count in stats
            ])
    def test_extract_persona(self):
        # Override self.addon with a persona.
        self.addon = addon_factory(persona_id=42, type=amo.ADDON_PERSONA)
        persona = self.addon.persona
        persona.header = u'myheader.jpg'
        persona.footer = u'myfooter.jpg'
        persona.accentcolor = u'336699'
        persona.textcolor = u'f0f0f0'
        persona.author = u'Me-me-me-Myself'
        persona.display_username = u'my-username'
        persona.save()
        extracted = self._extract()
        assert extracted['has_theme_rereview'] is False
        assert extracted['persona']['accentcolor'] == persona.accentcolor
        # We need the author that will go in theme_data here, which is
        # persona.display_username, not persona.author.
        assert extracted['persona']['author'] == persona.display_username
        assert extracted['persona']['header'] == persona.header
        assert extracted['persona']['footer'] == persona.footer
        assert extracted['persona']['is_new'] is False  # It has a persona_id.
        assert extracted['persona']['textcolor'] == persona.textcolor

        self.addon = addon_factory(persona_id=0, type=amo.ADDON_PERSONA)
        extracted = self._extract()
        assert extracted['persona']['is_new'] is True  # No persona_id.
Example #27
0
    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'))
        eq_(res.status_code, 200)
        eq_(pq(res.content)('.featured-addons').length, 2)
Example #28
0
 def test_themes_less_than_initial(self):
     """
     Number of themes in the pool is less than amount we want to check out.
     """
     addon_factory(type=amo.ADDON_PERSONA, status=self.status)
     reviewer = self.create_and_become_reviewer()
     assert len(_get_themes(mock.Mock(), reviewer)) == 1
     assert len(_get_themes(mock.Mock(), reviewer)) == 1
Example #29
0
    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
Example #30
0
    def test_total_reviews(self):
        addon = addon_factory()
        addon2 = addon_factory()

        # Add a purely unlisted add-on. It should not be considered when
        # calculating bayesian rating for the other add-ons.
        addon3 = addon_factory(total_reviews=3, average_rating=4)
        self.make_addon_unlisted(addon3)

        # Create a few reviews with various ratings.
        review = Review.objects.create(
            addon=addon, rating=3, user=user_factory())
        Review.objects.create(addon=addon, rating=3, user=user_factory())
        Review.objects.create(addon=addon, rating=2, user=user_factory())
        Review.objects.create(addon=addon, rating=1, user=user_factory())

        # On another addon as well.
        Review.objects.create(addon=addon2, rating=1, user=user_factory())
        Review.objects.create(addon=addon2, rating=1, user=user_factory())

        # addon_review_aggregates should ignore replies, so let's add one.
        Review.objects.create(
            addon=addon, rating=5, user=user_factory(), reply_to=review)

        # Make sure total_reviews hasn't been updated yet (because we are
        # mocking Review.refresh()).
        addon.reload()
        addon2.reload()
        assert addon.total_reviews == 0
        assert addon2.total_reviews == 0
        assert addon.bayesian_rating == 0
        assert addon.average_rating == 0
        assert addon2.bayesian_rating == 0
        assert addon2.average_rating == 0

        # Trigger the task and test results.
        addon_review_aggregates([addon.pk, addon2.pk])
        addon.reload()
        addon2.reload()
        assert addon.total_reviews == 4
        assert addon2.total_reviews == 2
        assert addon.bayesian_rating == 1.9821428571428572
        assert addon.average_rating == 2.25
        assert addon2.bayesian_rating == 1.375
        assert addon2.average_rating == 1.0

        # Trigger the task with a single add-on.
        Review.objects.create(addon=addon2, rating=5, user=user_factory())
        addon2.reload()
        assert addon2.total_reviews == 2

        addon_review_aggregates(addon2.pk)
        addon2.reload()
        assert addon2.total_reviews == 3
        assert addon.bayesian_rating == 1.9821428571428572
        assert addon.average_rating == 2.25
        assert addon2.bayesian_rating == 1.97915
        assert addon2.average_rating == 2.3333
 def setUp(self):
     super(TestThemeSearch, self).setUp()
     self.addon = addon_factory(type=amo.ADDON_PERSONA,
                                name='themeteam',
                                status=amo.STATUS_PENDING)
     self.refresh('default')
    def test_basic(self):
        av_min, _ = AppVersion.objects.get_or_create(
            application=amo.ANDROID.id, version='48.0')
        av_max, _ = AppVersion.objects.get_or_create(
            application=amo.ANDROID.id, version='48.*')
        av_seamonkey_min, _ = AppVersion.objects.get_or_create(
            application=amo.SEAMONKEY.id, version='2.49.3')
        av_seamonkey_max, _ = AppVersion.objects.get_or_create(
            application=amo.SEAMONKEY.id, version='2.49.*')
        # Those add-ons should not be deleted, because they are compatible with
        # at least Firefox or Firefox for Android.
        addon_factory()  # A pure Firefox add-on
        addon_factory(version_kw={'application': amo.ANDROID.id})
        addon_with_both_firefoxes = addon_factory()
        ApplicationsVersions.objects.get_or_create(
            application=amo.ANDROID.id,
            version=addon_with_both_firefoxes.current_version,
            min=av_min,
            max=av_max)
        addon_with_thunderbird_and_android = addon_factory(
            version_kw={'application': amo.THUNDERBIRD.id})
        ApplicationsVersions.objects.get_or_create(
            application=amo.ANDROID.id,
            version=addon_with_thunderbird_and_android.current_version,
            min=av_min,
            max=av_max)
        addon_with_firefox_and_seamonkey = addon_factory(
            version_kw={'application': amo.FIREFOX.id})
        ApplicationsVersions.objects.get_or_create(
            application=amo.SEAMONKEY.id,
            version=addon_with_firefox_and_seamonkey.current_version,
            min=av_seamonkey_min,
            max=av_seamonkey_max)
        addon_factory(
            status=amo.STATUS_NULL,  # Non-public, will cause it to be ignored.
            version_kw={'application': amo.THUNDERBIRD.id})

        # Those add-ons should be deleted as they are only compatible with
        # Thunderbird or Seamonkey, or both.
        addon = addon_factory(version_kw={'application': amo.THUNDERBIRD.id})
        addon2 = addon_factory(
            version_kw={
                'application': amo.SEAMONKEY.id,
                'min_app_version': '2.49.3',
                'max_app_version': '2.49.*'
            })
        addon3 = addon_factory(version_kw={'application': amo.THUNDERBIRD.id})
        ApplicationsVersions.objects.get_or_create(
            application=amo.SEAMONKEY.id,
            version=addon3.current_version,
            min=av_seamonkey_min,
            max=av_seamonkey_max)

        # We've manually changed the ApplicationVersions, so let's run
        # update_appsupport() on all public add-ons. In the real world that is
        # done automatically when uploading a new version, either through the
        # version_changed signal or via a cron that catches any versions that
        # somehow fell through the cracks once a day.
        update_appsupport(Addon.objects.public().values_list('pk', flat=True))

        assert Addon.objects.count() == 9

        with count_subtask_calls(
                pa.delete_addon_not_compatible_with_firefoxes) as calls:
            self.make_the_call()

        assert len(calls) == 1
        assert calls[0]['kwargs']['args'] == [[addon.pk, addon2.pk, addon3.pk]]
        assert not Addon.objects.filter(pk=addon.pk).exists()
        assert not Addon.objects.filter(pk=addon2.pk).exists()
        assert not Addon.objects.filter(pk=addon3.pk).exists()

        assert Addon.objects.count() == 6

        # Make sure ApplicationsVersions targeting Thunderbird or Seamonkey are
        # gone.
        assert not ApplicationsVersions.objects.filter(
            application=amo.SEAMONKEY.id).exists()
        assert not ApplicationsVersions.objects.filter(
            application=amo.THUNDERBIRD.id).exists()

        # Make sure AppSupport targeting Thunderbird or Seamonkey are gone for
        # add-ons we touched.
        assert not AppSupport.objects.filter(addon__in=(addon, addon2, addon3),
                                             app=amo.SEAMONKEY.id).exists()
        assert not AppSupport.objects.filter(addon__in=(addon, addon2, addon3),
                                             app=amo.THUNDERBIRD.id).exists()
Example #33
0
    def test_fetch_candidates(self):
        # We already have an add-on with a version awaiting review that should
        # be considered. Make sure its nomination date is in the past to test
        # ordering.
        self.version.update(nomination=self.days_ago(1))
        # Add a second file to self.version to test the distinct().
        file_factory(version=self.version,
                     status=amo.STATUS_AWAITING_REVIEW,
                     is_webextension=True)
        # Add reviewer flags disabling auto-approval for this add-on. It would
        # still be fetched as a candidate, just rejected later on when
        # calculating the verdict.
        AddonReviewerFlags.objects.create(addon=self.addon,
                                          auto_approval_disabled=True)

        # Add nominated add-on: it should be considered.
        new_addon = addon_factory(name='New Addon',
                                  status=amo.STATUS_NOMINATED,
                                  file_kw={
                                      'status': amo.STATUS_AWAITING_REVIEW,
                                      'is_webextension': True
                                  })
        new_addon_version = new_addon.versions.all()[0]
        new_addon_version.update(nomination=self.days_ago(2))
        # Even add an empty reviewer flags instance, that should not matter.
        AddonReviewerFlags.objects.create(addon=new_addon)

        # Add langpack: it should be considered.
        langpack = addon_factory(name='Langpack',
                                 type=amo.ADDON_LPAPP,
                                 status=amo.STATUS_NOMINATED,
                                 file_kw={
                                     'status': amo.STATUS_AWAITING_REVIEW,
                                     'is_webextension': True
                                 })
        langpack_version = langpack.versions.all()[0]
        langpack_version.update(nomination=self.days_ago(3))

        # Add a dictionary: it should also be considered.
        dictionary = addon_factory(name='Dictionary',
                                   type=amo.ADDON_DICT,
                                   status=amo.STATUS_NOMINATED,
                                   file_kw={
                                       'status': amo.STATUS_AWAITING_REVIEW,
                                       'is_webextension': True
                                   })
        dictionary_version = dictionary.versions.all()[0]
        dictionary_version.update(nomination=self.days_ago(4))

        # search engine plugins are considered now
        search_addon = addon_factory(name='Search', type=amo.ADDON_SEARCH)
        search_addon_version = version_factory(addon=search_addon,
                                               file_kw={
                                                   'status':
                                                   amo.STATUS_AWAITING_REVIEW,
                                                   'is_webextension': True
                                               },
                                               nomination=self.days_ago(5))

        # Some recommended add-ons - one nominated and one update.
        # They should be considered by fetch_candidate(), so that they get a
        # weight assigned etc - they will not be auto-approved but that's
        # handled at a later stage, when calculating the verdict.
        recommendable_addon_nominated = addon_factory(
            name='Recommendable Addon',
            status=amo.STATUS_NOMINATED,
            version_kw={
                'recommendation_approved': True,
                'nomination': self.days_ago(6)
            },
            file_kw={
                'status': amo.STATUS_AWAITING_REVIEW,
                'is_webextension': True
            },
        )
        DiscoveryItem.objects.create(recommendable=True,
                                     addon=recommendable_addon_nominated)

        recommended_addon = addon_factory(name='Recommended Addon', )
        recommended_addon_version = version_factory(
            addon=recommended_addon,
            recommendation_approved=True,
            nomination=self.days_ago(7),
            file_kw={
                'status': amo.STATUS_AWAITING_REVIEW,
                'is_webextension': True
            })
        DiscoveryItem.objects.create(recommendable=True,
                                     addon=recommended_addon)

        # Add-on with 3 versions:
        # - one webext, listed, public.
        # - one non-listed webext version awaiting review.
        # - one listed non-webext awaiting review (should be ignored)
        complex_addon = addon_factory(name='Complex Addon',
                                      file_kw={'is_webextension': True})
        complex_addon_version = version_factory(
            nomination=self.days_ago(8),
            addon=complex_addon,
            channel=amo.RELEASE_CHANNEL_UNLISTED,
            file_kw={
                'is_webextension': True,
                'status': amo.STATUS_AWAITING_REVIEW
            })
        version_factory(nomination=self.days_ago(9),
                        addon=complex_addon,
                        file_kw={'status': amo.STATUS_AWAITING_REVIEW})

        # Add-on with an already public version and an unlisted webext
        # awaiting review.
        complex_addon_2 = addon_factory(name='Second Complex Addon',
                                        file_kw={'is_webextension': True})
        complex_addon_2_version = version_factory(
            addon=complex_addon_2,
            channel=amo.RELEASE_CHANNEL_UNLISTED,
            nomination=self.days_ago(10),
            file_kw={
                'is_webextension': True,
                'status': amo.STATUS_AWAITING_REVIEW
            })

        # Disabled version with a webext waiting review (Still has to be
        # considered because unlisted doesn't care about disabled by user
        # state.
        user_disabled_addon = addon_factory(
            name='Disabled by user waiting review', disabled_by_user=True)
        user_disabled_addon_version = version_factory(
            nomination=self.days_ago(11),
            channel=amo.RELEASE_CHANNEL_UNLISTED,
            addon=user_disabled_addon,
            file_kw={
                'status': amo.STATUS_AWAITING_REVIEW,
                'is_webextension': True
            })

        # Pure unlisted upload. Addon status is "incomplete" as a result, but
        # it should still be considered because unlisted versions don't care
        # about that.
        pure_unlisted = addon_factory(name='Pure unlisted',
                                      version_kw={
                                          'channel':
                                          amo.RELEASE_CHANNEL_UNLISTED,
                                          'nomination': self.days_ago(12)
                                      },
                                      file_kw={
                                          'is_webextension': True,
                                          'status': amo.STATUS_AWAITING_REVIEW
                                      },
                                      status=amo.STATUS_NULL)
        pure_unlisted_version = pure_unlisted.versions.get()

        # Unlisted static theme.
        unlisted_theme = addon_factory(name='Unlisted theme',
                                       version_kw={
                                           'channel':
                                           amo.RELEASE_CHANNEL_UNLISTED,
                                           'nomination': self.days_ago(13)
                                       },
                                       file_kw={
                                           'is_webextension': True,
                                           'status': amo.STATUS_AWAITING_REVIEW
                                       },
                                       status=amo.STATUS_NULL,
                                       type=amo.ADDON_STATICTHEME)
        unlisted_theme_version = unlisted_theme.versions.get()

        # ---------------------------------------------------------------------
        # Add a bunch of add-ons in various states that should not be returned.
        # Public add-on with no updates.
        addon_factory(name='Already Public', file_kw={'is_webextension': True})

        # Mozilla Disabled add-on with updates.
        disabled_addon = addon_factory(
            name='Mozilla Disabled',
            status=amo.STATUS_DISABLED,
        )
        version_factory(addon=disabled_addon,
                        file_kw={
                            'status': amo.STATUS_AWAITING_REVIEW,
                            'is_webextension': True
                        })

        # Add-on with deleted version.
        addon_with_deleted_version = addon_factory(
            name='With deleted version awaiting review')
        deleted_version = version_factory(addon=addon_with_deleted_version,
                                          file_kw={
                                              'status':
                                              amo.STATUS_AWAITING_REVIEW,
                                              'is_webextension': True
                                          })
        deleted_version.delete()

        # Add-on with a non-webextension update.
        non_webext_addon = addon_factory(name='Non Webext waiting review')
        version_factory(addon=non_webext_addon,
                        file_kw={'status': amo.STATUS_AWAITING_REVIEW})

        # Somehow deleted add-on with a file still waiting for review.
        deleted_addon = addon_factory(
            name='Deleted Awaiting Review Somehow',
            status=amo.STATUS_DELETED,
        )
        version_factory(addon=deleted_addon,
                        file_kw={
                            'status': amo.STATUS_AWAITING_REVIEW,
                            'is_webextension': True
                        })

        # listed version belonging to an add-on disabled by user
        addon_factory(name='Listed Disabled by user',
                      disabled_by_user=True,
                      file_kw={
                          'status': amo.STATUS_AWAITING_REVIEW,
                          'is_webextension': True
                      })

        # Incomplete listed addon
        addon_factory(name='Incomplete listed',
                      status=amo.STATUS_NULL,
                      file_kw={
                          'status': amo.STATUS_AWAITING_REVIEW,
                          'is_webextension': True
                      })

        # Listed static theme
        addon_factory(name='Listed theme',
                      file_kw={
                          'is_webextension': True,
                          'status': amo.STATUS_AWAITING_REVIEW
                      },
                      status=amo.STATUS_NOMINATED,
                      type=amo.ADDON_STATICTHEME)

        # ---------------------------------------------------------------------
        # Gather the candidates.
        command = auto_approve.Command()
        command.post_review = True
        qs = command.fetch_candidates()

        # We should find these versions, in this exact order.
        expected = [(version.addon, version) for version in [
            unlisted_theme_version,
            pure_unlisted_version,
            user_disabled_addon_version,
            complex_addon_2_version,
            complex_addon_version,
            recommended_addon_version,
            recommendable_addon_nominated.current_version,
            search_addon_version,
            dictionary.current_version,
            langpack.current_version,
            new_addon.current_version,
            self.version,
        ]]

        assert [(version.addon, version) for version in qs] == expected
Example #34
0
    def test_run(self):
        # Pretend we went through the admin.
        self.rule.update(state=SCHEDULED)

        # Similar to test_run_on_chunk() except it needs to find the versions
        # by itself.
        other_addon = addon_factory(
            file_kw={'is_webextension': True},
            version_kw={'created': self.days_ago(1)},
        )
        other_addon_previous_current_version = other_addon.current_version
        included_versions = [
            # Only listed webextension version on this add-on.
            self.version,
            # Unlisted webextension version of this add-on.
            addon_factory(
                disabled_by_user=True,  # Doesn't matter.
                file_kw={
                    'is_webextension': True
                },
                version_kw={
                    'channel': amo.RELEASE_CHANNEL_UNLISTED
                },
            ).versions.get(),
            # Unlisted webextension version of an add-on that has multiple
            # versions.
            version_factory(
                addon=other_addon,
                created=self.days_ago(42),
                channel=amo.RELEASE_CHANNEL_UNLISTED,
                file_kw={'is_webextension': True},
            ),
            # Listed webextension versions of an add-on that has multiple
            # versions.
            other_addon_previous_current_version,
            version_factory(addon=other_addon,
                            file_kw={'is_webextension': True}),
        ]
        # Ignored versions:
        # Listed Webextension version belonging to mozilla disabled add-on.
        addon_factory(file_kw={
            'is_webextension': True
        },
                      status=amo.STATUS_DISABLED).current_version
        # Non-Webextension
        addon_factory(file_kw={'is_webextension': False}).current_version

        for version in Version.unfiltered.all():
            self.xpi_copy_over(version.all_files[0], 'webextension.xpi')

        # Run the task.
        run_yara_query_rule.delay(self.rule.pk)

        assert ScannerQueryResult.objects.count() == len(included_versions)
        assert sorted(
            ScannerQueryResult.objects.values_list(
                'version_id',
                flat=True)) == sorted(v.pk for v in included_versions)
        self.rule.reload()
        assert self.rule.state == COMPLETED
        assert self.rule.task_count == 1
        # We run tests in eager mode, so we can't retrieve the result for real,
        # just make sure the id was set to something.
        assert self.rule.celery_group_result_id is not None
Example #35
0
    def test_basic(self, sign_file_mock):
        file_kw = {'is_webextension': True, 'filename': 'webextension.xpi'}

        with freeze_time('2019-04-01'):
            addon_with_history = addon_factory(file_kw=file_kw)
            # Create a few more versions for this add-on to test that we only
            # re-sign current versions
            version_factory(addon=addon_with_history, file_kw=file_kw)
            version_factory(addon=addon_with_history, file_kw=file_kw)
            version_factory(addon=addon_with_history, file_kw=file_kw)

            addon_factory(file_kw=file_kw)
            addon_factory(type=amo.ADDON_STATICTHEME, file_kw=file_kw)
            addon_factory(type=amo.ADDON_LPAPP, file_kw=file_kw)
            addon_factory(type=amo.ADDON_DICT, file_kw=file_kw)

        # Don't resign add-ons created after April 4th 2019
        with freeze_time('2019-05-01'):
            addon_factory(file_kw=file_kw)
            addon_factory(type=amo.ADDON_STATICTHEME, file_kw=file_kw)

        # Search add-ons won't get re-signed, same with deleted and disabled
        # versions. Also, only public addons are being resigned
        addon_factory(type=amo.ADDON_SEARCH, file_kw=file_kw)
        addon_factory(status=amo.STATUS_DISABLED, file_kw=file_kw)
        addon_factory(status=amo.STATUS_AWAITING_REVIEW, file_kw=file_kw)
        addon_factory(status=amo.STATUS_NULL, file_kw=file_kw)

        call_command('process_addons', task='resign_addons_for_cose')

        assert sign_file_mock.call_count == 5
Example #36
0
 def create_file_upload(self):
     addon = addon_factory()
     return FileUpload.objects.create(addon=addon)
Example #37
0
 def test_repr_when_strict(self):
     addon = addon_factory(version_kw=self.version_kw,
                           file_kw=dict(strict_compatibility=True))
     version = addon.current_version
     assert six.text_type(version.apps.all()[0]) == 'Firefox 5.0 - 6.*'
def test_approve_addons_get_files_incomplete():
    """An incomplete add-on can't be approved."""
    addon = addon_factory(status=amo.STATUS_NULL)
    assert approve_addons.get_files([addon.guid]) == []
def test_approve_addons_get_review_type_already_approved():
    """The review type for a file that doesn't need approval is None."""
    addon = addon_factory(status=amo.STATUS_PUBLIC)
    file_ = addon.versions.get().files.get()
    file_.update(status=amo.STATUS_PUBLIC)
    assert approve_addons.get_review_type(file_) is None
    def test_basic(self):
        self.addon = addon_factory(
            average_daily_users=4242,
            average_rating=4.21,
            description=u'My Addôn description',
            file_kw={
                'hash': 'fakehash',
                'platform': amo.PLATFORM_WIN.id,
                'size': 42,
            },
            guid=generate_addon_guid(),
            homepage=u'https://www.example.org/',
            icon_type='image/png',
            name=u'My Addôn',
            public_stats=True,
            slug='my-addon',
            summary=u'My Addôn summary',
            support_email=u'*****@*****.**',
            support_url=u'https://support.example.org/support/my-addon/',
            tags=['some_tag', 'some_other_tag'],
            total_reviews=666,
            weekly_downloads=2147483647,
        )
        AddonUser.objects.create(user=user_factory(username='******'),
                                 addon=self.addon, listed=False)
        second_author = user_factory(
            username='******', display_name=u'Secönd Author')
        first_author = user_factory(
            username='******', display_name=u'First Authôr')
        AddonUser.objects.create(
            user=second_author, addon=self.addon, position=2)
        AddonUser.objects.create(
            user=first_author, addon=self.addon, position=1)
        second_preview = Preview.objects.create(
            addon=self.addon, position=2,
            caption={'en-US': u'My câption', 'fr': u'Mön tîtré'})
        first_preview = Preview.objects.create(addon=self.addon, position=1)

        av_min = AppVersion.objects.get_or_create(
            application=amo.THUNDERBIRD.id, version='2.0.99')[0]
        av_max = AppVersion.objects.get_or_create(
            application=amo.THUNDERBIRD.id, version='3.0.99')[0]
        ApplicationsVersions.objects.get_or_create(
            application=amo.THUNDERBIRD.id, version=self.addon.current_version,
            min=av_min, max=av_max)
        # Reset current_version.compatible_apps now that we've added an app.
        del self.addon.current_version.compatible_apps

        cat1 = Category.from_static_category(
            CATEGORIES[amo.FIREFOX.id][amo.ADDON_EXTENSION]['bookmarks'])
        cat1.save()
        AddonCategory.objects.create(addon=self.addon, category=cat1)
        cat2 = Category.from_static_category(
            CATEGORIES[amo.FIREFOX.id][amo.ADDON_EXTENSION]['alerts-updates'])
        cat2.save()
        AddonCategory.objects.create(addon=self.addon, category=cat2)
        cat3 = Category.from_static_category(
            CATEGORIES[amo.THUNDERBIRD.id][amo.ADDON_EXTENSION]['calendar'])
        cat3.save()
        AddonCategory.objects.create(addon=self.addon, category=cat3)

        result = self.serialize()

        assert result['id'] == self.addon.pk

        assert result['average_daily_users'] == self.addon.average_daily_users
        assert result['categories'] == {
            'firefox': ['alerts-updates', 'bookmarks'],
            'thunderbird': ['calendar']}

        assert result['current_beta_version'] is None

        assert result['current_version']
        self._test_version(
            self.addon.current_version, result['current_version'])

        assert result['authors']
        assert len(result['authors']) == 2
        assert result['authors'][0] == {
            'id': first_author.pk,
            'name': first_author.name,
            'url': absolutify(first_author.get_url_path())}
        assert result['authors'][1] == {
            'id': second_author.pk,
            'name': second_author.name,
            'url': absolutify(second_author.get_url_path())}

        assert result['edit_url'] == absolutify(self.addon.get_dev_url())
        assert result['default_locale'] == self.addon.default_locale
        assert result['description'] == {'en-US': self.addon.description}
        assert result['guid'] == self.addon.guid
        assert result['has_eula'] is False
        assert result['has_privacy_policy'] is False
        assert result['homepage'] == {'en-US': self.addon.homepage}
        assert result['icon_url'] == absolutify(self.addon.get_icon_url(64))
        assert result['is_disabled'] == self.addon.is_disabled
        assert result['is_experimental'] == self.addon.is_experimental is False
        assert result['is_listed'] == self.addon.is_listed
        assert result['is_source_public'] == self.addon.view_source
        assert result['name'] == {'en-US': self.addon.name}
        assert result['last_updated'] == (
            self.addon.last_updated.isoformat() + 'Z')

        assert result['previews']
        assert len(result['previews']) == 2

        result_preview = result['previews'][0]
        assert result_preview['id'] == first_preview.pk
        assert result_preview['caption'] is None
        assert result_preview['image_url'] == absolutify(
            first_preview.image_url)
        assert result_preview['thumbnail_url'] == absolutify(
            first_preview.thumbnail_url)

        result_preview = result['previews'][1]
        assert result_preview['id'] == second_preview.pk
        assert result_preview['caption'] == {
            'en-US': u'My câption',
            'fr': u'Mön tîtré'
        }
        assert result_preview['image_url'] == absolutify(
            second_preview.image_url)
        assert result_preview['thumbnail_url'] == absolutify(
            second_preview.thumbnail_url)

        assert result['ratings'] == {
            'average': self.addon.average_rating,
            'count': self.addon.total_reviews,
        }
        assert result['public_stats'] == self.addon.public_stats
        assert result['review_url'] == absolutify(
            reverse('editors.review', args=[self.addon.pk]))
        assert result['slug'] == self.addon.slug
        assert result['status'] == 'public'
        assert result['summary'] == {'en-US': self.addon.summary}
        assert result['support_email'] == {'en-US': self.addon.support_email}
        assert result['support_url'] == {'en-US': self.addon.support_url}
        assert 'theme_data' not in result
        assert set(result['tags']) == set(['some_tag', 'some_other_tag'])
        assert result['type'] == 'extension'
        assert result['url'] == absolutify(self.addon.get_url_path())
        assert result['weekly_downloads'] == self.addon.weekly_downloads

        return result
    def test_is_experimental(self):
        self.addon = addon_factory(is_experimental=True)
        result = self.serialize()

        assert result['is_experimental'] is True
    def test_basic(self):
        now = self.days_ago(0)
        license = License.objects.create(
            name={
                'en-US': u'My License',
                'fr': u'Mä Licence',
            },
            text={
                'en-US': u'Lorem ipsum dolor sit amet, has nemore patrioqué',
            },
            url='http://license.example.com/'

        )
        addon = addon_factory(
            file_kw={
                'hash': 'fakehash',
                'platform': amo.PLATFORM_WIN.id,
                'size': 42,
            },
            version_kw={
                'license': license,
                'min_app_version': '50.0',
                'max_app_version': '*',
                'releasenotes': {
                    'en-US': u'Release notes in english',
                    'fr': u'Notes de version en français',
                },
                'reviewed': now,
            }
        )

        self.version = addon.current_version
        first_file = self.version.files.latest('pk')
        file_factory(
            version=self.version, platform=amo.PLATFORM_MAC.id)
        second_file = self.version.files.latest('pk')
        # Force reload of all_files cached property.
        del self.version.all_files

        result = self.serialize()
        assert result['id'] == self.version.pk

        assert result['compatibility'] == {
            'firefox': {'max': u'*', 'min': u'50.0'}
        }

        assert result['files']
        assert len(result['files']) == 2

        assert result['files'][0]['id'] == first_file.pk
        assert result['files'][0]['created'] == (
            first_file.created.isoformat() + 'Z')
        assert result['files'][0]['hash'] == first_file.hash
        assert result['files'][0]['platform'] == 'windows'
        assert result['files'][0]['size'] == first_file.size
        assert result['files'][0]['status'] == 'public'
        assert result['files'][0]['url'] == first_file.get_url_path(src='')

        assert result['files'][1]['id'] == second_file.pk
        assert result['files'][1]['created'] == (
            second_file.created.isoformat() + 'Z')
        assert result['files'][1]['hash'] == second_file.hash
        assert result['files'][1]['platform'] == 'mac'
        assert result['files'][1]['size'] == second_file.size
        assert result['files'][1]['status'] == 'public'
        assert result['files'][1]['url'] == second_file.get_url_path(src='')

        assert result['edit_url'] == absolutify(addon.get_dev_url(
            'versions.edit', args=[self.version.pk], prefix_only=True))
        assert result['release_notes'] == {
            'en-US': u'Release notes in english',
            'fr': u'Notes de version en français',
        }
        assert result['license']
        assert dict(result['license']) == {
            'name': {'en-US': u'My License', 'fr': u'Mä Licence'},
            'text': {
                'en-US': u'Lorem ipsum dolor sit amet, has nemore patrioqué',
            },
            'url': 'http://license.example.com/',
        }
        assert result['reviewed'] == now.isoformat() + 'Z'
        assert result['url'] == absolutify(self.version.get_url_path())
    def test_unlisted(self):
        self.addon = addon_factory(name=u'My Unlisted Addôn', is_listed=False)
        result = self.serialize()

        assert result['id'] == self.addon.pk
        assert result['is_listed'] == self.addon.is_listed
    def test_is_source_public(self):
        self.addon = addon_factory(view_source=True)
        result = self.serialize()

        assert result['is_source_public'] is True
Example #45
0
 def test_repr_when_compatible(self):
     addon = addon_factory(version_kw=self.version_kw)
     version = addon.current_version
     assert six.text_type(version.apps.all()[0]) == 'Firefox 5.0 and later'
    def test_is_listed(self):
        self.addon = addon_factory(is_listed=False)
        result = self.serialize()

        assert result['is_listed'] is False
Example #47
0
 def setUp(self):
     self.addon1 = addon_factory()
     self.addon2 = addon_factory()
     self.file1 = self.addon1.current_version.all_files[0]
    def test_is_disabled(self):
        self.addon = addon_factory(disabled_by_user=True)
        result = self.serialize()

        assert result['is_disabled'] is True
Example #49
0
    def test_affects_correct_addons(self):
        # *not considered* - Non auto-approved add-on
        addon_factory()

        # *not considered* - Non auto-approved add-on that has an
        # AutoApprovalSummary entry
        AutoApprovalSummary.objects.create(
            version=addon_factory().current_version,
            verdict=amo.NOT_AUTO_APPROVED)

        # *not considered* -Add-on with the current version not auto-approved
        extra_addon = addon_factory()
        AutoApprovalSummary.objects.create(
            version=extra_addon.current_version, verdict=amo.AUTO_APPROVED)
        extra_addon.current_version.update(created=self.days_ago(1))
        version_factory(addon=extra_addon)

        # *not considered* - current version is auto-approved but doesn't
        # have recent abuse reports or low ratings
        auto_approved_addon = addon_factory()
        AutoApprovalSummary.objects.create(
            version=auto_approved_addon.current_version,
            verdict=amo.AUTO_APPROVED)

        # *considered* - current version is auto-approved and
        # has a recent rating with rating <= 3
        auto_approved_addon1 = addon_factory()
        summary = AutoApprovalSummary.objects.create(
            version=auto_approved_addon1.current_version,
            verdict=amo.AUTO_APPROVED)
        Rating.objects.create(
            created=summary.modified + timedelta(days=3),
            addon=auto_approved_addon1,
            version=auto_approved_addon1.current_version,
            rating=2, body='Apocalypse', user=user_factory()),

        # *not considered* - current version is auto-approved but
        # has a recent rating with rating > 3
        auto_approved_addon2 = addon_factory()
        summary = AutoApprovalSummary.objects.create(
            version=auto_approved_addon2.current_version,
            verdict=amo.AUTO_APPROVED)
        Rating.objects.create(
            created=summary.modified + timedelta(days=3),
            addon=auto_approved_addon2,
            version=auto_approved_addon2.current_version,
            rating=4, body='Apocalypse', user=user_factory()),

        # *not considered* - current version is auto-approved but
        # has a recent rating with rating > 3
        auto_approved_addon3 = addon_factory()
        summary = AutoApprovalSummary.objects.create(
            version=auto_approved_addon3.current_version,
            verdict=amo.AUTO_APPROVED)
        Rating.objects.create(
            created=summary.modified + timedelta(days=3),
            addon=auto_approved_addon3,
            version=auto_approved_addon3.current_version,
            rating=4, body='Apocalypse', user=user_factory()),

        # *not considered* - current version is auto-approved but
        # has a low rating that isn't recent enough
        auto_approved_addon4 = addon_factory()
        summary = AutoApprovalSummary.objects.create(
            version=auto_approved_addon4.current_version,
            verdict=amo.AUTO_APPROVED)
        Rating.objects.create(
            created=summary.modified - timedelta(days=3),
            addon=auto_approved_addon4,
            version=auto_approved_addon4.current_version,
            rating=1, body='Apocalypse', user=user_factory()),

        # *considered* - current version is auto-approved and
        # has a recent abuse report
        auto_approved_addon5 = addon_factory()
        summary = AutoApprovalSummary.objects.create(
            version=auto_approved_addon5.current_version,
            verdict=amo.AUTO_APPROVED)
        AbuseReport.objects.create(
            addon=auto_approved_addon5,
            created=summary.modified + timedelta(days=3))

        # *not considered* - current version is auto-approved but
        # has an abuse report that isn't recent enough
        auto_approved_addon6 = addon_factory()
        summary = AutoApprovalSummary.objects.create(
            version=auto_approved_addon6.current_version,
            verdict=amo.AUTO_APPROVED)
        AbuseReport.objects.create(
            addon=auto_approved_addon6,
            created=summary.modified - timedelta(days=3))

        # *considered* - current version is auto-approved and
        # has an abuse report through it's author that is recent enough
        author = user_factory()
        auto_approved_addon7 = addon_factory(users=[author])
        summary = AutoApprovalSummary.objects.create(
            version=auto_approved_addon7.current_version,
            verdict=amo.AUTO_APPROVED)
        AbuseReport.objects.create(
            user=author,
            created=summary.modified + timedelta(days=3))

        # *not considered* - current version is auto-approved and
        # has an abuse report through it's author that is recent enough
        # BUT the abuse report is deleted.
        author = user_factory()
        auto_approved_addon8 = addon_factory(users=[author])
        summary = AutoApprovalSummary.objects.create(
            version=auto_approved_addon8.current_version,
            verdict=amo.AUTO_APPROVED)
        AbuseReport.objects.create(
            user=author,
            state=AbuseReport.STATES.DELETED,
            created=summary.modified + timedelta(days=3))

        # *not considered* - current version is auto-approved and
        # has a recent rating with rating <= 3
        # but the rating is deleted.
        auto_approved_addon9 = addon_factory()
        summary = AutoApprovalSummary.objects.create(
            version=auto_approved_addon9.current_version,
            verdict=amo.AUTO_APPROVED)
        Rating.objects.create(
            created=summary.modified + timedelta(days=3),
            addon=auto_approved_addon9,
            version=auto_approved_addon9.current_version,
            deleted=True,
            rating=2, body='Apocalypse', user=user_factory()),

        # *considered* - current version is auto-approved and
        # has an abuse report through it's author that is recent enough
        # Used to test that we only recalculate the weight for
        # the most recent version
        author = user_factory()
        auto_approved_addon8 = addon_factory(
            users=[author], version_kw={'version': '0.1'})

        AutoApprovalSummary.objects.create(
            version=auto_approved_addon8.current_version,
            verdict=amo.AUTO_APPROVED)

        # Let's create a new `current_version` and summary
        current_version = version_factory(
            addon=auto_approved_addon8, version='0.2')

        summary = AutoApprovalSummary.objects.create(
            version=current_version,
            verdict=amo.AUTO_APPROVED)

        AbuseReport.objects.create(
            user=author,
            created=summary.modified + timedelta(days=3))

        mod = 'olympia.reviewers.tasks.AutoApprovalSummary.calculate_weight'
        with mock.patch(mod) as calc_weight_mock:
            with count_subtask_calls(
                    process_addons.recalculate_post_review_weight) as calls:
                call_command(
                    'process_addons',
                    task='constantly_recalculate_post_review_weight')

        assert len(calls) == 1
        assert calls[0]['kwargs']['args'] == [[
            auto_approved_addon1.pk,
            auto_approved_addon5.pk,
            auto_approved_addon7.pk,
            auto_approved_addon8.pk,
        ]]

        # Only 4 calls for each add-on, doesn't consider the extra version
        # that got created for addon 8
        assert calc_weight_mock.call_count == 4
 def test_with_addon(self):
     addon_factory(guid=self.block.guid, name='Addón náme')
     serializer = BlockSerializer(instance=self.block)
     assert serializer.data['addon_name'] == {'en-US': 'Addón náme'}
Example #51
0
    def test_latest_public_compatible_with(self):
        # Add compatible add-ons. We're going to request versions compatible
        # with 58.0.
        compatible_pack1 = addon_factory(
            name='Spanish Language Pack',
            type=amo.ADDON_LPAPP,
            target_locale='es',
            file_kw={'strict_compatibility': True},
            version_kw={
                'min_app_version': '57.0',
                'max_app_version': '57.*'
            })
        compatible_pack1.current_version.update(created=self.days_ago(2))
        compatible_version1 = version_factory(
            addon=compatible_pack1,
            file_kw={'strict_compatibility': True},
            min_app_version='58.0',
            max_app_version='58.*')
        compatible_version1.update(created=self.days_ago(1))
        compatible_pack2 = addon_factory(
            name='French Language Pack',
            type=amo.ADDON_LPAPP,
            target_locale='fr',
            file_kw={'strict_compatibility': True},
            version_kw={
                'min_app_version': '58.0',
                'max_app_version': '58.*'
            })
        compatible_version2 = compatible_pack2.current_version
        compatible_version2.update(created=self.days_ago(2))
        version_factory(addon=compatible_pack2,
                        file_kw={'strict_compatibility': True},
                        min_app_version='59.0',
                        max_app_version='59.*')
        # Add a more recent version for both add-ons, that would be compatible
        # with 58.0, but is not public/listed so should not be returned.
        version_factory(addon=compatible_pack1,
                        file_kw={'strict_compatibility': True},
                        min_app_version='58.0',
                        max_app_version='58.*',
                        channel=amo.RELEASE_CHANNEL_UNLISTED)
        version_factory(addon=compatible_pack2,
                        file_kw={
                            'strict_compatibility': True,
                            'status': amo.STATUS_DISABLED
                        },
                        min_app_version='58.0',
                        max_app_version='58.*')
        # And for the first pack, add a couple of versions that are also
        # compatible. They are older so should appear after.
        extra_compatible_version_1 = version_factory(
            addon=compatible_pack1,
            file_kw={'strict_compatibility': True},
            min_app_version='58.0',
            max_app_version='58.*')
        extra_compatible_version_1.update(created=self.days_ago(3))
        extra_compatible_version_2 = version_factory(
            addon=compatible_pack1,
            file_kw={'strict_compatibility': True},
            min_app_version='58.0',
            max_app_version='58.*')
        extra_compatible_version_2.update(created=self.days_ago(4))

        # Add a few of incompatible add-ons.
        incompatible_pack1 = addon_factory(
            name='German Language Pack (incompatible with 58.0)',
            type=amo.ADDON_LPAPP,
            target_locale='fr',
            file_kw={'strict_compatibility': True},
            version_kw={
                'min_app_version': '56.0',
                'max_app_version': '56.*'
            })
        version_factory(addon=incompatible_pack1,
                        file_kw={'strict_compatibility': True},
                        min_app_version='59.0',
                        max_app_version='59.*')
        addon_factory(name='Italian Language Pack (incompatible with 58.0)',
                      type=amo.ADDON_LPAPP,
                      target_locale='it',
                      file_kw={'strict_compatibility': True},
                      version_kw={
                          'min_app_version': '59.0',
                          'max_app_version': '59.*'
                      })
        # Even add a pack with a compatible version... not public. And another
        # one with a compatible version... not listed.
        incompatible_pack2 = addon_factory(
            name='Japanese Language Pack (public, but 58.0 version is not)',
            type=amo.ADDON_LPAPP,
            target_locale='ja',
            file_kw={'strict_compatibility': True},
            version_kw={
                'min_app_version': '57.0',
                'max_app_version': '57.*'
            })
        version_factory(addon=incompatible_pack2,
                        min_app_version='58.0',
                        max_app_version='58.*',
                        file_kw={
                            'status': amo.STATUS_AWAITING_REVIEW,
                            'strict_compatibility': True
                        })
        incompatible_pack3 = addon_factory(
            name='Nederlands Language Pack (58.0 version is unlisted)',
            type=amo.ADDON_LPAPP,
            target_locale='ja',
            file_kw={'strict_compatibility': True},
            version_kw={
                'min_app_version': '57.0',
                'max_app_version': '57.*'
            })
        version_factory(addon=incompatible_pack3,
                        min_app_version='58.0',
                        max_app_version='58.*',
                        channel=amo.RELEASE_CHANNEL_UNLISTED,
                        file_kw={'strict_compatibility': True})

        appversions = {
            'min': version_int('58.0'),
            'max': version_int('58.0a'),
        }
        qs = Version.objects.latest_public_compatible_with(
            amo.FIREFOX.id, appversions)

        expected_versions = [
            compatible_version1, compatible_version2,
            extra_compatible_version_1, extra_compatible_version_2
        ]
        assert list(qs) == expected_versions
Example #52
0
 def get_object(self):
     version_preview = VersionPreview.objects.create(
         version=addon_factory().current_version)
     return version_preview
    def test_basic(self, migrate_legacy_dictionarymock, index_addons_mock):
        self.counter = 0

        def side_effect(*args, **kwargs):
            self.counter += 1
            if self.counter == 2:
                raise ValidationError('Dummy validation error')

        addon_factory()
        addon_factory(type=amo.ADDON_LPAPP)
        addon_factory(type=amo.ADDON_STATICTHEME)
        addon_factory(type=amo.ADDON_DICT, file_kw={'is_webextension': True})
        addon_factory(type=amo.ADDON_DICT,
                      target_locale='es',
                      status=amo.STATUS_DISABLED)
        addon_factory(type=amo.ADDON_DICT,
                      target_locale='it',
                      disabled_by_user=True)
        self.addon = addon_factory(type=amo.ADDON_DICT, target_locale='fr')
        self.addon2 = addon_factory(type=amo.ADDON_DICT, target_locale=None)
        self.addon3 = addon_factory(type=amo.ADDON_DICT, target_locale='')
        migrate_legacy_dictionarymock.side_effect = side_effect
        index_addons_mock.reset_mock()

        call_command('process_addons',
                     task='migrate_legacy_dictionaries_to_webextension')
        assert migrate_legacy_dictionarymock.call_count == 3
        actual_calls = (migrate_legacy_dictionarymock.call_args_list[0][0][0],
                        migrate_legacy_dictionarymock.call_args_list[1][0][0],
                        migrate_legacy_dictionarymock.call_args_list[2][0][0])
        expected_calls = (self.addon, self.addon2, self.addon3)
        assert actual_calls == expected_calls
        # self.addon2 will raise a ValidationError because of the side_effect
        # above, so we should only reindex 1 and 3.
        assert index_addons_mock.call_args[0][0] == [self.addon, self.addon3]
Example #54
0
 def test_repr_when_unicode(self):
     addon = addon_factory(
         version_kw=dict(min_app_version=u'ك', max_app_version=u'ك'))
     version = addon.current_version
     assert six.text_type(version.apps.all()[0]) == u'Firefox ك - ك'
Example #55
0
 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'))
Example #56
0
 def test_repr_when_low_app_support(self):
     addon = addon_factory(
         version_kw=dict(min_app_version='3.0', max_app_version='3.5'))
     version = addon.current_version
     assert six.text_type(version.apps.all()[0]) == 'Firefox 3.0 - 3.5'
 def setUp(self):
     super(TestDeletedThemeLookup, self).setUp()
     self.deleted = addon_factory(type=amo.ADDON_PERSONA)
     self.deleted.update(status=amo.STATUS_DELETED)
Example #58
0
 def test_repr_when_binary(self):
     addon = addon_factory(version_kw=self.version_kw,
                           file_kw=dict(binary_components=True))
     version = addon.current_version
     assert six.text_type(version.apps.all()[0]) == 'Firefox 5.0 - 6.*'
 def test_no_license(self):
     addon = addon_factory()
     self.version = addon.current_version
     result = self.serialize()
     assert result['id'] == self.version.pk
     assert result['license'] is None
    def test_icon_url_without_icon_type_set(self):
        self.addon = addon_factory()
        result = self.serialize()

        assert result['id'] == self.addon.pk
        assert result['icon_url'] == absolutify(self.addon.get_icon_url(64))