def test_compatible_version(self): addon = addon_factory() version = version_factory(addon=addon, version='99') version_factory( addon=addon, version='100', channel=amo.RELEASE_CHANNEL_UNLISTED) assert find_compatible_version(addon, amo.FIREFOX.id) == version
def test_all_versions_shown_for_admin(self): self.login_as_admin() listed_ver = version_factory( addon=self.addon, channel=amo.RELEASE_CHANNEL_LISTED, version='4.0', created=self.days_ago(1)) unlisted_ver = version_factory( addon=self.addon, channel=amo.RELEASE_CHANNEL_UNLISTED, version='5.0') assert self.addon.versions.count() == 3 res = self.client.get(self.file_url()) doc = pq(res.content) left_select = doc('#id_left') assert left_select('optgroup').attr('label') == self.version.version file_options = left_select('option.status-public') assert len(file_options) == 3, left_select.html() # Check the files in the list are the two we added and the default. assert file_options.eq(0).attr('value') == str( unlisted_ver.all_files[0].pk) assert file_options.eq(1).attr('value') == str( listed_ver.all_files[0].pk) assert file_options.eq(2).attr('value') == str(self.file.pk) # Check there are prefixes on the labels for the channels assert file_options.eq(0).text().endswith('[Self]') assert file_options.eq(1).text().endswith('[AMO]') assert file_options.eq(2).text().endswith('[AMO]')
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
def test_version_detail(self): version = version_factory(addon=self.addon, version='2.0') version.update(created=self.days_ago(2)) version = version_factory(addon=self.addon, version='2.1b', file_kw={'status': amo.STATUS_BETA}) version.update(created=self.days_ago(1)) version_factory(addon=self.addon, version='2.2b', file_kw={'status': amo.STATUS_BETA}) urls = [(v.version, reverse('addons.versions', args=[self.addon.slug, v.version])) for v in self.addon.versions.all()] version, url = urls[0] assert version == '2.2b' r = self.client.get(url, follow=True) self.assert3xx(r, self.url_list_betas + '?page=1#version-%s' % version) version, url = urls[1] assert version == '2.1b' r = self.client.get(url, follow=True) self.assert3xx(r, self.url_list_betas + '?page=2#version-%s' % version) version, url = urls[2] assert version == '2.0' r = self.client.get(url, follow=True) self.assert3xx(r, self.url_list + '?page=1#version-%s' % version) version, url = urls[3] assert version == '1.0' r = self.client.get(url, follow=True) self.assert3xx(r, self.url_list + '?page=2#version-%s' % version)
def test_extract_version_and_files(self): version = self.addon.current_version file_factory(version=version, platform=PLATFORM_MAC.id) current_beta_version = version_factory( addon=self.addon, file_kw={ 'status': amo.STATUS_BETA, 'is_webextension': True, 'is_mozilla_signed_extension': True, }) # Give one of the versions some webext permissions to test that. WebextPermission.objects.create( file=current_beta_version.all_files[0], permissions=['bookmarks', 'random permission'] ) unlisted_version = version_factory( addon=self.addon, channel=amo.RELEASE_CHANNEL_UNLISTED) extracted = self._extract() assert extracted['current_version'] assert extracted['current_version']['id'] == version.pk # Because strict_compatibility is False, the max version we record in # the index is an arbitrary super high version. assert extracted['current_version']['compatible_apps'] == { FIREFOX.id: { 'min': 2000000200100L, 'max': 9999000000200100, 'max_human': '4.0', 'min_human': '2.0', } }
def test_review_files(self): version_factory(addon=self.addon, created=self.version.created - timedelta(days=1), file_kw={'status': amo.STATUS_PUBLIC}) for status in REVIEW_FILES_STATUSES: self.setup_data(status=status) assert self.helper.handler.__class__ == ReviewFiles
def test_get_diff_newline_both_no_newline(): addon = addon_factory(file_kw={'filename': 'webextension_no_id.xpi'}) original_version = addon.current_version AddonGitRepository.extract_and_commit_from_version(original_version) parent_version = version_factory( addon=addon, file_kw={'filename': 'webextension_no_id.xpi'}) repo = AddonGitRepository.extract_and_commit_from_version(parent_version) # Let's remove the newline apply_changes(repo, parent_version, '{"id": "random"}', 'manifest.json') version = version_factory( addon=addon, file_kw={'filename': 'webextension_no_id.xpi'}) repo = AddonGitRepository.extract_and_commit_from_version(version) # Now we're adding it again apply_changes(repo, version, '{"id": "new random id"}', 'manifest.json') changes = repo.get_diff( commit=version.git_hash, parent=parent_version.git_hash) assert len(changes) == 1 assert changes[0]['new_ending_new_line'] is False assert changes[0]['old_ending_new_line'] is False
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
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 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()
def test_only_consider_beta_for_downgrade_error_if_uploading_a_beta(self): """Make sure we don't raise the webextension downgrade error when uploading a public legacy version we have a beta webext.""" # Create a beta webext with a version number higher than the existing # legacy, but lower than the legacy we're about to upload... version_factory(addon=self.addon, version='1.0b1', file_kw={ 'is_webextension': True, 'status': amo.STATUS_BETA, }) file_ = amo.tests.AMOPaths().file_fixture_path( 'delicious_bookmarks-2.1.106-fx.xpi') upload = FileUpload.objects.create(path=file_, addon=self.addon) tasks.validate(upload, listed=True) upload.refresh_from_db() assert upload.processed_validation['errors'] == 0 assert upload.valid # Do consider previous betas when uploading a beta, though. file_ = amo.tests.AMOPaths().file_fixture_path( 'beta-extension.xpi') upload = FileUpload.objects.create(path=file_, addon=self.addon) tasks.validate(upload, listed=True) upload.refresh_from_db() assert not upload.valid expected = ['validation', 'messages', 'webext_downgrade'] assert upload.processed_validation['messages'][0]['id'] == expected assert upload.processed_validation['messages'][0]['type'] == 'error'
def test_version_detail(self): version = version_factory(addon=self.addon, version='2.0') version.update(created=self.days_ago(2)) version = version_factory(addon=self.addon, version='2.1') version.update(created=self.days_ago(1)) urls = [(v.version, reverse('addons.versions', args=[self.addon.slug, v.version])) for v in self.addon.versions.all()] version, url = urls[0] assert version == '2.1' response = self.client.get(url, follow=True) self.assert3xx( response, self.url_list + '?page=1#version-%s' % version) version, url = urls[1] assert version == '2.0' response = self.client.get(url, follow=True) self.assert3xx( response, self.url_list + '?page=2#version-%s' % version) version, url = urls[2] assert version == '1.0' response = self.client.get(url, follow=True) self.assert3xx( response, self.url_list + '?page=3#version-%s' % version)
def test_version_list_doesnt_show_unreviewed_versions_public_addon(self): version = self.addon.current_version.version version_factory( addon=self.addon, file_kw={'status': amo.STATUS_AWAITING_REVIEW}, version='2.1') doc = self.get_content() assert len(doc('.version')) == 1 assert doc('.version').attr('id') == 'version-%s' % version
def test_review_unlisted_while_a_listed_version_is_awaiting_review(self): self.make_addon_unlisted(self.addon) self.version.reload() version_factory( addon=self.addon, channel=amo.RELEASE_CHANNEL_LISTED, file_kw={'status': amo.STATUS_AWAITING_REVIEW}) self.addon.update(status=amo.STATUS_NOMINATED) assert self.get_helper()
def test_version_list_does_not_show_betas_by_default(self): version = self.addon.current_version.version version_factory( addon=self.addon, file_kw={'status': amo.STATUS_BETA}, version='2.1b') doc = self.get_content() assert len(doc('.version')) == 1 assert doc('.version').attr('id') == 'version-%s' % version
def addon(transactional_db, create_superuser, pytestconfig): """Creates a custom addon named 'Ui-Addon'. This addon will be a featured addon and will have a featured collecton attatched to it. It will belong to the user created by the 'create_superuser' fixture. It has 1 preview, 5 reviews, and 2 authors. The second author is named 'ui-tester2'. It has a version number as well as a beta version. """ if not pytestconfig.option.usingliveserver: return default_icons = [x[0] for x in icons() if x[0].startswith('icon/')] addon = addon_factory( status=STATUS_PUBLIC, type=ADDON_EXTENSION, average_daily_users=5567, users=[UserProfile.objects.get(username='******')], average_rating=5, description=u'My Addon description', file_kw={ 'hash': 'fakehash', 'platform': amo.PLATFORM_ALL.id, 'size': 42, }, guid=generate_addon_guid(), homepage=u'https://www.example.org/', icon_type=random.choice(default_icons), name=u'Ui-Addon', public_stats=True, slug='ui-test', summary=u'My Addon summary', support_email=u'*****@*****.**', support_url=u'https://support.example.org/support/ui-test-addon/', tags=['some_tag', 'another_tag', 'ui-testing', 'selenium', 'python'], total_reviews=888, weekly_downloads=2147483647, developer_comments='This is a testing addon, used within pytest.', is_experimental=True, ) Preview.objects.create(addon=addon, position=1) Review.objects.create(addon=addon, rating=5, 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()) addon.reload() AddonUser.objects.create(user=user_factory(username='******'), addon=addon, listed=True) version_factory(addon=addon, file_kw={'status': amo.STATUS_BETA}, version='1.1beta') addon.save() generate_collection(addon, app=FIREFOX) print('Created addon {0} for testing successfully'.format(addon.name)) return addon
def test_valid_versions(self): addon = Addon.objects.get(id=3615) additional_version = version_factory( addon=addon, version='0.1') amo.tests.file_factory(version=additional_version) version_factory( addon=addon, version='0.2', file_kw={'status': amo.STATUS_DISABLED}) assert list( Version.objects.valid()) == [additional_version, self.version]
def test_validity_still_valid_if_new_version_in_different_channel(self): version_factory(addon=self.addon, channel=amo.RELEASE_CHANNEL_UNLISTED) assert self.version == self.addon.find_latest_version( channel=amo.RELEASE_CHANNEL_LISTED) # The token isn't expired. assert not self.token.is_expired() # It's also still valid, since our version is still the latest listed # one. assert self.token.is_valid()
def test_basic(self): # These add-ons should be disabled completely since they only have a # single legacy file. should_be_fully_disabled = [ addon_factory(), addon_factory(type=amo.ADDON_LPAPP), addon_factory(type=amo.ADDON_THEME), ] # This one has a legacy and a non-legacy version, so only the legacy # File & Version should be disabled. should_have_old_version_disabled = [ addon_factory(created=self.days_ago(42), version_kw={'created': self.days_ago(42)}), ] version_factory( addon=should_have_old_version_disabled[0], file_kw={'is_webextension': True}) # These should *not* have any File instance disabled, they should be # kept intact. should_be_kept_intact = [ addon_factory(file_kw={'is_webextension': True}), addon_factory(file_kw={'is_mozilla_signed_extension': True}), addon_factory(file_kw={'is_mozilla_signed_extension': True, 'is_webextension': True}), addon_factory(type=amo.ADDON_DICT), addon_factory(type=amo.ADDON_SEARCH), ] call_command('process_addons', task='disable_legacy_files') for addon in should_be_fully_disabled: addon.reload() assert addon.status == amo.STATUS_NULL # No public version left. assert addon.current_version is None file_ = addon.versions.all()[0].files.all()[0] assert file_.status == amo.STATUS_DISABLED for addon in should_have_old_version_disabled: addon.reload() assert addon.status == amo.STATUS_PUBLIC assert addon.current_version file_ = addon.current_version.files.all()[0] assert file_.status == amo.STATUS_PUBLIC file_ = addon.versions.exclude( pk=addon.current_version.pk)[0].files.all()[0] assert file_.status == amo.STATUS_DISABLED for addon in should_be_kept_intact: addon.reload() assert addon.status == amo.STATUS_PUBLIC assert addon.current_version file_ = addon.versions.all()[0].all_files[0] assert file_.status == amo.STATUS_PUBLIC
def test_latest_unlisted_version(self): self.addon = addon_factory() version_factory( addon=self.addon, channel=amo.RELEASE_CHANNEL_UNLISTED, version='1.1') assert self.addon.latest_unlisted_version result = self.serialize() # In this serializer latest_unlisted_version is omitted even if there # is one, because it's limited to users with specific rights. assert 'latest_unlisted_version' not in result
def create_featured_addon_with_version(self): """Creates a custom addon named 'Ui-Addon'. This addon will be a featured addon and will have a featured collecton attatched to it. It will belong to the user uitest. It has 1 preview, 5 reviews, and 2 authors. The second author is named 'ui-tester2'. It has a version number as well as a beta version. """ default_icons = [x[0] for x in icons() if x[0].startswith('icon/')] addon = addon_factory( status=STATUS_PUBLIC, type=ADDON_EXTENSION, average_daily_users=5000, users=[UserProfile.objects.get(username='******')], average_rating=5, description=u'My Addon description', file_kw={ 'hash': 'fakehash', 'platform': amo.PLATFORM_ALL.id, 'size': 42, }, guid=generate_addon_guid(), icon_type=random.choice(default_icons), name=u'Ui-Addon', public_stats=True, slug='ui-test-2', summary=u'My Addon summary', tags=['some_tag', 'another_tag', 'ui-testing', 'selenium', 'python'], total_ratings=500, weekly_downloads=9999999, developer_comments='This is a testing addon.', ) Preview.objects.create(addon=addon, position=1) Rating.objects.create(addon=addon, rating=5, user=user_factory()) Rating.objects.create(addon=addon, rating=5, user=user_factory()) Rating.objects.create(addon=addon, rating=5, user=user_factory()) Rating.objects.create(addon=addon, rating=5, user=user_factory()) Rating.objects.create(addon=addon, rating=5, user=user_factory()) Rating.objects.create(addon=addon, rating=5, user=user_factory()) Rating.objects.create(addon=addon, rating=5, user=user_factory()) Rating.objects.create(addon=addon, rating=5, user=user_factory()) AddonUser.objects.create(user=user_factory(username='******'), addon=addon, listed=True) version_factory(addon=addon, file_kw={'status': amo.STATUS_BETA}, version='1.1beta') addon.save() generate_collection(addon, app=FIREFOX) print( 'Created addon {0} for testing successfully' .format(addon.name))
def test_rejected_can_request_review(self): self.addon.update(status=amo.STATUS_NULL) latest_version = self.addon.find_latest_version( channel=amo.RELEASE_CHANNEL_LISTED) for file_ in latest_version.files.all(): file_.update(status=amo.STATUS_DISABLED) version_factory(addon=self.addon, file_kw={'status': amo.STATUS_DISABLED}) doc = pq(self.client.get(self.url).content) buttons = doc('.version-status-actions form button') # We should only show the links for one of the disabled versions. assert buttons.length == 1 assert buttons.text() == u'Request Review'
def test_channel_prefix_not_shown_when_no_mixed_channels(self): self.login_as_admin() version_factory(addon=self.addon, channel=amo.RELEASE_CHANNEL_LISTED) assert self.addon.versions.count() == 2 res = self.client.get(self.file_url()) doc = pq(res.content) left_select = doc('#id_left') assert left_select('optgroup').attr('label') == self.version.version # Check there are NO prefixes on the labels for the channels file_options = left_select('option.status-public') assert not file_options.eq(0).text().endswith('[Self]') assert not file_options.eq(1).text().endswith('[AMO]') assert not file_options.eq(2).text().endswith('[AMO]')
def test_is_compatible_by_default_type(self): # Types in NO_COMPAT are compatible by default. addon = Addon.objects.get(id=3615) version = version_factory(addon=addon) addon.update(type=amo.ADDON_PERSONA) assert version.is_compatible_by_default assert version.is_compatible_app(amo.FIREFOX)
def test_is_compatible_by_default(self): # Base test for fixture before the rest. Should be compatible by # default. addon = Addon.objects.get(id=3615) version = version_factory(addon=addon) assert version.is_compatible_by_default assert version.is_compatible_app(amo.FIREFOX)
def test_show_latest_unlisted_version_unlisted(self): unlisted_version = version_factory( addon=self.addon, channel=amo.RELEASE_CHANNEL_UNLISTED) unlisted_version.update(created=self.days_ago(1)) result = self._test_url() assert result['latest_unlisted_version'] assert result['latest_unlisted_version']['id'] == unlisted_version.pk
def test_latest_unlisted_version_with_rights(self): self.serializer_class = self.serializer_class_with_unlisted_data self.addon = addon_factory() version_factory( addon=self.addon, channel=amo.RELEASE_CHANNEL_UNLISTED, version='1.1') assert self.addon.latest_unlisted_version result = self.serialize() # In this serializer latest_unlisted_version is present. assert result['latest_unlisted_version'] self._test_version( self.addon.latest_unlisted_version, result['latest_unlisted_version']) assert result['latest_unlisted_version']['url'] == absolutify('')
def test_get_raw_diff_cache(): addon = addon_factory(file_kw={'filename': 'webextension_no_id.xpi'}) original_version = addon.current_version AddonGitRepository.extract_and_commit_from_version(original_version) version = version_factory( addon=addon, file_kw={'filename': 'webextension_no_id.xpi'}) repo = AddonGitRepository.extract_and_commit_from_version(version) # Let's a file apply_changes(repo, version, '', 'manifest.json', delete=True) with mock.patch('olympia.lib.git.pygit2.Repository.diff') as mocked_diff: repo.get_diff( commit=version.git_hash, parent=original_version.git_hash) repo.get_diff( commit=version.git_hash, parent=original_version.git_hash) mocked_diff.assert_called_once() assert (version.git_hash, original_version.git_hash) in repo._diff_cache
def setUp(self): # Create File objects for version 1.0 and 1.1. self.addon = addon_factory( guid='test-desktop@nowhere', slug='test-amo-addon', version_kw={'version': '1.0'}) self.version = self.addon.current_version self.file = self.version.files.get() self.version_1_1 = version_factory(addon=self.addon, version='1.1') self.file_1_1 = self.version_1_1.files.get() # Creating the files and versions above resets this. self.addon.update(status=amo.STATUS_PUBLIC) # Create a FileUpload object for an XPI containing version 1.1. path = os.path.join(settings.ROOT, 'src/olympia/devhub/tests/addons/desktop.xpi') self.file_upload = FileUpload.objects.create(path=path) self.xpi_version = '1.1' # Patch validation tasks that we expect the validator to call. self.patchers = [] self.save_file = self.patch( 'olympia.devhub.tasks.handle_file_validation_result').subtask self.save_upload = self.patch( 'olympia.devhub.tasks.handle_upload_validation_result').subtask self.validate_file = self.patch( 'olympia.devhub.tasks.validate_file').subtask self.validate_upload = self.patch( 'olympia.devhub.tasks.validate_file_path').subtask
def test_no_upgrade_annotation_no_version(self): """Make sure there's no workaround the downgrade error.""" self.addon.update(guid='guid@xpi') file_ = amo.tests.AMOPaths().file_fixture_path( 'delicious_bookmarks-no-version.xpi') self.update_files(is_webextension=True) deleted_version = version_factory( addon=self.addon, file_kw={'is_webextension': False}) deleted_version.delete() upload = FileUpload.objects.create(path=file_, addon=self.addon) upload.addon.version = None upload.addon.save() upload.save(update_fields=('version',)) upload.refresh_from_db() tasks.validate(upload, listed=True) upload.refresh_from_db() expected = [u'testcases_installrdf', u'_test_rdf', u'missing_addon'] validation = upload.processed_validation assert validation['messages'][0]['id'] == expected assert validation['messages'][0]['type'] == 'error'
def test_get_results_with_good_blocked_versions(self): self.create_switch('enable-scanner-results-api', active=True) # Result labelled as "good" because auto-approve has been confirmed. version_1 = version_factory(addon=addon_factory()) result_1 = ScannerResult.objects.create(scanner=CUSTOMS, version=version_1) VersionLog.objects.create( activity_log=ActivityLog.create( action=amo.LOG.CONFIRM_AUTO_APPROVED, version=version_1, user=self.user, ), version=version_1, ) # Oh noes! The version has been blocked. block_1 = Block.objects.create(guid=version_1.addon.guid, updated_by=self.user) block_activity_log_save(block_1, change=False) response = self.client.get(self.url) results = self.assert_json_results(response, expected_results=1) assert results[0]['id'] == result_1.id assert results[0]['label'] == LABEL_BAD
def test_version_pagination(self): addon = addon_factory(users=[user_factory()]) first_file = addon.current_version.all_files[0] [version_factory(addon=addon) for i in range(0, 30)] self.detail_url = reverse('admin:addons_addon_change', args=(addon.pk, )) user = user_factory(email='*****@*****.**') self.grant_permission(user, 'Addons:Edit') self.grant_permission(user, 'Admin:Advanced') self.client.login(email=user.email) response = self.client.get(self.detail_url, follow=True) assert response.status_code == 200 assert addon.guid in response.content.decode('utf-8') assert len(pq(response.content)('.field-version__version')) == 30 next_url = self.detail_url + '?page=2' assert next_url in response.content.decode('utf-8') response = self.client.get(next_url, follow=True) assert response.status_code == 200 assert addon.guid in response.content.decode('utf-8') assert len(pq(response.content)('.field-version__version')) == 1 assert pq( response.content)('#id_files-0-id')[0].attrib['value'] == (str( first_file.id))
def test_only_affects_auto_approved_and_unconfirmed(self): # Non auto-approved add-on, should not be considered. addon_factory() # Non auto-approved add-on that has an AutoApprovalSummary entry, # should not be considered. AutoApprovalSummary.objects.create( version=addon_factory().current_version, verdict=amo.NOT_AUTO_APPROVED) # Add-on with the current version not auto-approved, should not be # considered. 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) # Add-on that was auto-approved but already confirmed, should not be # considered, it's too late. already_confirmed_addon = addon_factory() AutoApprovalSummary.objects.create( version=already_confirmed_addon.current_version, verdict=amo.AUTO_APPROVED, confirmed=True) # Add-on that should be considered because it's current version is # auto-approved. auto_approved_addon = addon_factory() AutoApprovalSummary.objects.create( version=auto_approved_addon.current_version, verdict=amo.AUTO_APPROVED) # Add some extra versions that should not have an impact. version_factory(addon=auto_approved_addon, file_kw={'status': amo.STATUS_AWAITING_REVIEW}) version_factory(addon=auto_approved_addon, channel=amo.RELEASE_CHANNEL_UNLISTED) with count_subtask_calls( process_addons.recalculate_post_review_weight) as calls: call_command('process_addons', task='recalculate_post_review_weight') assert len(calls) == 1 assert calls[0]['kwargs']['args'] == [[auto_approved_addon.pk]]
def test_webextension_cannot_be_downgraded_ignore_deleted_version(self): """Make sure even deleting the previous version does not prevent the downgrade error.""" file_ = amo.tests.AMOPaths().file_fixture_path( 'delicious_bookmarks-2.1.106-fx.xpi') self.update_files(is_webextension=True) deleted_version = version_factory( addon=self.addon, file_kw={'is_webextension': False}) deleted_version.delete() upload = FileUpload.objects.create(path=file_, addon=self.addon) tasks.validate(upload, listed=True) upload.refresh_from_db() expected = ['validation', 'messages', 'legacy_addons_unsupported'] validation = upload.processed_validation assert validation['messages'][0]['id'] == expected assert validation['messages'][0]['type'] == 'error'
def test_current_beta_version(self): self.addon = addon_factory() self.beta_version = version_factory( addon=self.addon, file_kw={'status': amo.STATUS_BETA}, version='1.1beta') result = self.serialize() assert result['current_beta_version'] self._test_version( self.beta_version, result['current_beta_version'], ) assert result['current_beta_version']['url'] == absolutify( reverse('addons.versions', args=[self.addon.slug, self.beta_version.version])) # Just in case, test that current version is still present & different. assert result['current_version'] assert result['current_version'] != result['current_beta_version'] self._test_version(self.addon.current_version, result['current_version'])
def test_reject_multiple_versions(self): old_version = self.version self.version = version_factory(addon=self.addon, version='3.0') # An extra file should not change anything. file_factory(version=self.version, platform=amo.PLATFORM_LINUX.id) self.setup_data(amo.STATUS_PUBLIC, file_status=amo.STATUS_PUBLIC) # Safeguards. assert isinstance(self.helper.handler, ReviewFiles) assert self.addon.status == amo.STATUS_PUBLIC assert self.file.status == amo.STATUS_PUBLIC assert self.addon.current_version.is_public() data = self.get_data().copy() data['versions'] = self.addon.versions.all() self.helper.set_data(data) self.helper.handler.reject_multiple_versions() self.addon.reload() self.file.reload() assert self.addon.status == amo.STATUS_NULL assert self.addon.current_version is None assert list(self.addon.versions.all()) == [self.version, old_version] assert self.file.status == amo.STATUS_DISABLED assert len(mail.outbox) == 1 assert mail.outbox[0].to == [self.addon.authors.all()[0].email] assert mail.outbox[0].subject == ( u"Mozilla Add-ons: One or more versions of Delicious Bookmarks " u"didn't pass review") assert ('Version(s) affected and disabled:\n3.0, 2.1.072' in mail.outbox[0].body) log_token = ActivityLogToken.objects.get() assert log_token.uuid.hex in mail.outbox[0].reply_to[0] assert self.check_log_count(amo.LOG.REJECT_VERSION.id) == 2 assert self.check_log_count(amo.LOG.REJECT_CONTENT.id) == 0
def _handle_version(self, data): if (self.addon.versions(manager='unfiltered_for_relations').filter( version=data['version']).exists()): print('Skipping %s (version already exists' % data['version']) return file_data = data['file'] file_kw = { 'hash': file_data['hash'], 'filename': basename(urlparse(file_data['url']).path), 'status': amo.STATUS_CHOICES_API_LOOKUP[file_data['status']], 'size': file_data['size'], 'is_mozilla_signed_extension': (file_data['is_mozilla_signed_extension']), 'strict_compatibility': (data['is_strict_compatibility_enabled']), } version_kw = { 'version': data['version'], # FIXME: maybe reviewed/created would make sense at least, to # get more or less the correct ordering ? # Everything else we don't really care about at the moment. } print('Creating version %s' % data['version']) with atomic(): version = version_factory(addon=self.addon, file_kw=file_kw, **version_kw) # Download the file to the right path. print('Downloading file for version %s' % data['version']) self._download_file(file_data['url'], version.file)
def test_extract_addon_with_more_versions_than_batch_size(self): version_1 = self.addon.current_version version_2 = version_factory( addon=self.addon, file_kw={ 'filename': 'webextension_no_id.xpi', }, ) repo = AddonGitRepository(self.addon) entry = GitExtractionEntry.objects.create(addon=self.addon) assert not version_1.git_hash assert not version_2.git_hash assert not repo.is_extracted # First execution of the CRON task. self.command.extract_addon(entry, batch_size=1) version_1.refresh_from_db() version_2.refresh_from_db() entry.refresh_from_db() assert repo.is_extracted assert version_1.git_hash # We only git-extracted the first version because of batch_size=1. assert not version_2.git_hash # We keep the entry and we set `in_progress` to `False` because we # still need to extract the second version. assert not entry.in_progress assert GitExtractionEntry.objects.filter(pk=entry.pk).exists() # Second execution of the CRON task. self.command.extract_addon(entry, batch_size=1) version_2.refresh_from_db() assert repo.is_extracted assert version_2.git_hash assert not GitExtractionEntry.objects.filter(pk=entry.pk).exists()
def test_serialize_deleted_file(self): expected_filename = 'manifest.json' parent_version = self.addon.current_version new_version = version_factory(addon=self.addon, file_kw={ 'filename': 'webextension_no_id.xpi', 'is_webextension': True, }) repo = AddonGitRepository.extract_and_commit_from_version(new_version) apply_changes(repo, new_version, '', expected_filename, delete=True) file = self.addon.current_version.current_file data = self.serialize(file, parent_version=parent_version) assert data['download_url'] is None # We deleted the selected file, so there should be a diff. assert data['diff'] is not None assert data['diff']['mode'] == 'D' assert data['mimetype'] == 'application/json' assert data['sha256'] is None assert data['size'] is None assert data['mime_category'] is None assert data['filename'] == expected_filename
def test_addon_mixed_channels(self): first_version = self.addon.current_version second_version = version_factory(addon=self.addon, channel=amo.RELEASE_CHANNEL_UNLISTED) response = self.client.get(self.url) assert response.status_code == 200 doc = pq(response.content) first_expected_review_link = reverse('editors.review', args=(self.addon.slug, )) elms = doc('a[href="%s"]' % first_expected_review_link) assert len(elms) == 1 assert elms[0].attrib['title'] == str(first_version.pk) assert elms[0].text == first_version.version second_expected_review_link = reverse('editors.review', args=( 'unlisted', self.addon.slug, )) elms = doc('a[href="%s"]' % second_expected_review_link) assert len(elms) == 1 assert elms[0].attrib['title'] == str(second_version.pk) assert elms[0].text == second_version.version
def test_cant_reply_to_old_version(self): old_version = self.addon.find_latest_version(channel=amo.RELEASE_CHANNEL_LISTED) old_version.update(created=self.days_ago(1)) new_version = version_factory(addon=self.addon) assert new_version == self.addon.find_latest_version( channel=amo.RELEASE_CHANNEL_LISTED ) self.user = user_factory() self.grant_permission(self.user, 'Addons:Review') self.client.login_api(self.user) # First check we can reply to new version new_url = reverse_ns( 'version-reviewnotes-list', kwargs={'addon_pk': self.addon.pk, 'version_pk': new_version.pk}, ) response = self.client.post(new_url, {'comments': 'comménty McCómm€nt'}) assert response.status_code == 201 assert self.get_review_activity_queryset().count() == 1 # The check we can't reply to the old version response = self._post_reply() assert response.status_code == 400 assert self.get_review_activity_queryset().count() == 1
def test_public_to_public_already_had_webextension_tag(self): self.file.update(is_webextension=True) Tag(tag_text='firefox57').save_tag(self.addon) assert (set(self.addon.tags.all().values_list( 'tag_text', flat=True)) == set(['firefox57'])) self.addon.current_version.update(created=self.days_ago(1)) self.version = version_factory( addon=self.addon, channel=amo.RELEASE_CHANNEL_LISTED, version='3.0.42', file_kw={'status': amo.STATUS_AWAITING_REVIEW}) self.file = self.version.files.all()[0] self.setup_data(amo.STATUS_PUBLIC) # Safeguards. assert isinstance(self.helper.handler, helpers.ReviewFiles) assert self.addon.status == amo.STATUS_PUBLIC assert self.file.status == amo.STATUS_AWAITING_REVIEW assert self.addon.current_version.files.all()[0].status == ( amo.STATUS_PUBLIC) self.helper.handler.process_public() assert (set(self.addon.tags.all().values_list( 'tag_text', flat=True)) == set(['firefox57']))
def test_known_ip_adresses(self): self.user.update(last_login_ip='127.1.2.3') Rating.objects.create( addon=addon_factory(), user=self.user, ip_address='127.1.2.3') dummy_addon = addon_factory() Rating.objects.create( addon=dummy_addon, version=dummy_addon.current_version, user=self.user, ip_address='128.1.2.3') Rating.objects.create( addon=dummy_addon, version=version_factory(addon=dummy_addon), user=self.user, ip_address='129.1.2.4') Rating.objects.create( addon=addon_factory(), user=self.user, ip_address='130.1.2.4') Rating.objects.create( addon=addon_factory(), user=self.user, ip_address='130.1.2.4') Rating.objects.create( addon=dummy_addon, user=user_factory(), ip_address='255.255.0.0') model_admin = UserAdmin(UserProfile, admin.site) doc = pq(model_admin.known_ip_adresses(self.user)) result = doc('ul li').text().split() assert len(result) == 4 assert (set(result) == set(['130.1.2.4', '128.1.2.3', '129.1.2.4', '127.1.2.3']))
def test_version_is_public(self): addon = Addon.objects.get(id=3615) version = version_factory(addon=addon) # Base test. Everything is in order, the version should be public. assert version.is_public() # Non-public file. self._reset_version(version) version.all_files[0].status = amo.STATUS_DISABLED assert not version.is_public() # Deleted version. self._reset_version(version) version.deleted = True assert not version.is_public() # Non-public addon. self._reset_version(version) is_public_path = 'olympia.addons.models.Addon.is_public' with mock.patch(is_public_path) as is_addon_public: is_addon_public.return_value = False assert not version.is_public()
def test_only_affects_auto_approved( self, recalculate_post_review_weight_mock): # Non auto-approved add-on, should not be considered. addon_factory() # Non auto-approved add-on that has an AutoApprovalSummary entry, # should not be considered. AutoApprovalSummary.objects.create( version=addon_factory().current_version, verdict=amo.NOT_AUTO_APPROVED) # Add-on with the current version not auto-approved, should not be # considered. 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) # Add-on that should be considered because it's current version is # auto-approved. auto_approved_addon = addon_factory() AutoApprovalSummary.objects.create( version=auto_approved_addon.current_version, verdict=amo.AUTO_APPROVED) # Add some extra versions that should not have an impact. version_factory( addon=auto_approved_addon, file_kw={'status': amo.STATUS_AWAITING_REVIEW}) version_factory( addon=auto_approved_addon, channel=amo.RELEASE_CHANNEL_UNLISTED) call_command( 'process_addons', task='recalculate_post_review_weight') assert recalculate_post_review_weight_mock.call_count == 1 recalculate_post_review_weight_mock.assert_called_with( args=[[auto_approved_addon.pk]], kwargs={})
def test_source_upload_path_utf8_chars(self): addon = Addon.objects.get(id=3615) addon.update(slug=u'crosswarpex-확장') version = version_factory(addon=addon, version='0.1') uploaded_name = source_upload_path(version, 'crosswarpex-확장.tar.gz') assert uploaded_name.endswith(u'crosswarpex-확장-0.1-src.tar.gz')
def test_source_upload_path(self): addon = Addon.objects.get(id=3615) version = version_factory(addon=addon, version='0.1') uploaded_name = source_upload_path(version, 'foo.tar.gz') assert uploaded_name.endswith(u'a3615-0.1-src.tar.gz')
def test_invalidate_d2c_version_signals_on_save(self, inv_mock): addon = Addon.objects.get(pk=3615) version_factory(addon=addon) assert inv_mock.called
def test_validity_version_out_of_date(self): version_factory(addon=self.addon, channel=amo.RELEASE_CHANNEL_LISTED) # The token isn't expired. assert not self.token.is_expired() # But is invalid, because the version isn't the latest version. assert not self.token.is_valid()
def test_invalid_versions_not_accepted(self): user = user_factory() self.grant_permission(user, 'Admin:Tools') self.grant_permission(user, 'Reviews:Admin') self.client.login(email=user.email) self.addon.current_version.update(version='123.4b5') version_factory(addon=self.addon, version='678') # Update min_version in self.block to a version that doesn't exist self.block.update(min_version='444.4a') response = self.client.get(self.change_url, follow=True) content = response.content.decode('utf-8') doc = pq(content) ver_list = doc('#id_min_version option') assert len(ver_list) == 4 assert ver_list.eq(0).attr['value'] == '444.4a' assert ver_list.eq(0).text() == '(invalid)' assert ver_list.eq(1).attr['value'] == '0' assert ver_list.eq(2).attr['value'] == '123.4b5' assert ver_list.eq(3).attr['value'] == '678' ver_list = doc('#id_max_version option') assert len(ver_list) == 3 assert ver_list.eq(0).attr['value'] == '*' assert ver_list.eq(1).attr['value'] == '123.4b5' assert ver_list.eq(2).attr['value'] == '678' data = { 'url': 'https://foo.baa', 'reason': 'some other reason', 'include_in_legacy': True, '_continue': 'Save and continue editing', } # Try saving the form with the same min_version response = self.client.post( self.change_url, dict( min_version='444.4a', # current value, but not a version. max_version=self.addon.current_version.version, # valid **data), follow=True) assert response.status_code == 200 assert b'Invalid version' in response.content self.block = self.block.reload() assert self.block.min_version == '444.4a' # not changed assert self.block.max_version == '*' # not changed either. assert not ActivityLog.objects.for_addons(self.addon).exists() doc = pq(content) assert doc('#id_min_version option').eq(0).attr['value'] == '444.4a' # Change to a version that exists response = self.client.post(self.change_url, dict(min_version='123.4b5', max_version='*', **data), follow=True) assert response.status_code == 200 assert b'Invalid version' not in response.content self.block = self.block.reload() assert self.block.min_version == '123.4b5' # changed assert self.block.max_version == '*' assert ActivityLog.objects.for_addons(self.addon).exists() # the value shouldn't be in the list of versions either any longer. assert b'444.4a' not in response.content
def test_add_single(self): user = user_factory() self.grant_permission(user, 'Admin:Tools') self.grant_permission(user, 'Reviews:Admin') self.client.login(email=user.email) addon = addon_factory(guid='guid@', name='Danger Danger', version_kw={'version': '1.2a'}) first_version = addon.current_version second_version = version_factory(addon=addon, version='3') pending_version = version_factory( addon=addon, version='5.999', file_kw={'status': amo.STATUS_AWAITING_REVIEW}) response = self.client.get(self.single_url + '?guid=guid@', follow=True) content = response.content.decode('utf-8') assert 'Add-on GUIDs (one per line)' not in content assert 'guid@' in content assert 'Danger Danger' in content assert str(addon.average_daily_users) in content assert Block.objects.count() == 0 # Check we didn't create it already assert 'Block History' in content # Create the block response = self.client.post(self.single_url + '?guid=guid@', { 'min_version': '0', 'max_version': addon.current_version.version, 'url': 'dfd', 'reason': 'some reason', '_continue': 'Save', }, follow=True) assert response.status_code == 200 assert Block.objects.count() == 1 block = Block.objects.first() assert block.addon == addon log = ActivityLog.objects.for_addons(addon).last() assert log.action == amo.LOG.BLOCKLIST_BLOCK_ADDED.id assert log.arguments == [addon, addon.guid, block] assert log.details['min_version'] == '0' assert log.details['max_version'] == addon.current_version.version assert log.details['reason'] == 'some reason' block_log = ActivityLog.objects.for_block(block).filter( action=log.action).last() assert block_log == log block_log_by_guid = ActivityLog.objects.for_guidblock('guid@').filter( action=log.action).last() assert block_log_by_guid == log assert log == ActivityLog.objects.for_version(first_version).last() assert log == ActivityLog.objects.for_version(second_version).last() assert not ActivityLog.objects.for_version(pending_version).exists() content = response.content.decode('utf-8') todaysdate = datetime.datetime.now().date() assert f'<a href="dfd">{todaysdate}</a>' in content assert f'Block added by {user.name}: guid@' in content assert f'versions 0 - {addon.current_version.version}' in content assert f'Included in legacy blocklist' not in content
def test_unlisted(self): addon = addon_factory() self.version = version_factory(addon=addon, channel=amo.RELEASE_CHANNEL_UNLISTED) result = self.serialize() assert result['channel'] == 'unlisted'
def setup_data(self): user = user_factory() for idx in range(0, 5): addon_factory() # one version, 0 - * Block.objects.create( addon=addon_factory(file_kw={'is_signed': True, 'is_webextension': True}), updated_by=user, ) # one version, 0 - 9999 Block.objects.create( addon=addon_factory( version_kw={'version': '11.7'}, file_kw={'is_signed': True, 'is_webextension': True}, ), updated_by=user, max_version='9999', ) # one version, 0 - *, unlisted Block.objects.create( addon=addon_factory( version_kw={'channel': amo.RELEASE_CHANNEL_UNLISTED}, file_kw={'is_signed': True, 'is_webextension': True}, ), updated_by=user, ) # five versions, but only two within block (123.40, 123.5) self.five_ver_block = Block.objects.create( addon=addon_factory( version_kw={'version': '123.40'}, file_kw={'is_signed': True, 'is_webextension': True}, ), updated_by=user, max_version='123.45', ) self.five_ver_123_40 = self.five_ver_block.addon.current_version self.five_ver_123_5 = version_factory( addon=self.five_ver_block.addon, version='123.5', deleted=True, file_kw={'is_signed': True, 'is_webextension': True}, ) self.five_ver_123_45_1 = version_factory( addon=self.five_ver_block.addon, version='123.45.1', file_kw={'is_signed': True, 'is_webextension': True}, ) # these two would be included if they were signed and webextensions self.not_signed_version = version_factory( addon=self.five_ver_block.addon, version='123.5.1', file_kw={'is_signed': False, 'is_webextension': True}, ) self.not_webext_version = version_factory( addon=self.five_ver_block.addon, version='123.5.2', file_kw={'is_signed': True, 'is_webextension': False}, ) # no matching versions (edge cases) self.over = Block.objects.create( addon=addon_factory( version_kw={'version': '0.1'}, file_kw={'is_signed': True, 'is_webextension': True}, ), updated_by=user, max_version='0', ) self.under = Block.objects.create( addon=addon_factory( version_kw={'version': '9998.0'}, file_kw={'is_signed': True, 'is_webextension': True}, ), updated_by=user, min_version='9999', ) # A blocked addon has been uploaded and deleted before reused_2_1_addon = addon_factory( # this a previous, superceeded, addon that should be included status=amo.STATUS_DELETED, # they should all be deleted version_kw={'version': '2.1'}, file_kw={'is_signed': True, 'is_webextension': True}, ) self.addon_deleted_before_2_1_ver = reused_2_1_addon.versions.all()[0] reused_2_5_addon = addon_factory( # And this is an earlier addon that should also be included status=amo.STATUS_DELETED, # they should all be deleted version_kw={'version': '2.5'}, file_kw={'is_signed': True, 'is_webextension': True}, ) self.addon_deleted_before_2_5_ver = reused_2_5_addon.versions.all()[0] current_addon = addon_factory( version_kw={'version': '2'}, file_kw={'is_signed': True, 'is_webextension': True}, ) self.addon_deleted_before_unblocked_ver = current_addon.current_version self.addon_deleted_before_unsigned_ver = version_factory( addon=current_addon, version='2.1', # not signed, but shouldn't override the signed 2.1 version file_kw={'is_signed': False, 'is_webextension': True}, ) version_factory( addon=current_addon, version='3.0', file_kw={'is_signed': True, 'is_webextension': True}, ) reused_2_1_addon.update(guid=GUID_REUSE_FORMAT.format(current_addon.id)) reused_2_5_addon.update(guid=GUID_REUSE_FORMAT.format(reused_2_1_addon.id)) reused_2_1_addon.addonguid.update(guid=current_addon.guid) reused_2_5_addon.addonguid.update(guid=current_addon.guid) self.addon_deleted_before_block = Block.objects.create( guid=current_addon.guid, min_version='2.0.1', updated_by=user )
def test_extract_version_and_files(self): version = self.addon.current_version file_factory(version=version, platform=PLATFORM_MAC.id) unlisted_version = version_factory( addon=self.addon, channel=amo.RELEASE_CHANNEL_UNLISTED, file_kw={ 'is_webextension': True, }) # Give one of the versions some webext permissions to test that. WebextPermission.objects.create( file=unlisted_version.all_files[0], permissions=['bookmarks', 'random permission'] ) extracted = self._extract() assert extracted['current_version'] assert extracted['current_version']['id'] == version.pk # Because strict_compatibility is False, the max version we record in # the index is an arbitrary super high version. assert extracted['current_version']['compatible_apps'] == { FIREFOX.id: { 'min': 2000000200100, 'max': 9999000000200100, 'max_human': '4.0', 'min_human': '2.0', } } assert extracted['current_version']['reviewed'] == version.reviewed assert extracted['current_version']['version'] == version.version for index, file_ in enumerate(version.all_files): extracted_file = extracted['current_version']['files'][index] assert extracted_file['id'] == file_.pk assert extracted_file['created'] == file_.created assert extracted_file['filename'] == file_.filename assert extracted_file['hash'] == file_.hash assert extracted_file['is_webextension'] == file_.is_webextension assert extracted_file['is_restart_required'] == ( file_.is_restart_required) assert extracted_file['is_mozilla_signed_extension'] == ( file_.is_mozilla_signed_extension) assert extracted_file['platform'] == file_.platform assert extracted_file['size'] == file_.size assert extracted_file['status'] == file_.status assert extracted_file['webext_permissions_list'] == [] assert set(extracted['platforms']) == set([PLATFORM_MAC.id, PLATFORM_ALL.id]) version = unlisted_version assert extracted['latest_unlisted_version'] assert extracted['latest_unlisted_version']['id'] == version.pk # Because strict_compatibility is False, the max version we record in # the index is an arbitrary super high version. assert extracted['latest_unlisted_version']['compatible_apps'] == { FIREFOX.id: { 'min': 4009900200100, 'max': 9999000000200100, 'max_human': '5.0.99', 'min_human': '4.0.99', } } assert ( extracted['latest_unlisted_version']['version'] == version.version) for idx, file_ in enumerate(version.all_files): extracted_file = extracted['latest_unlisted_version']['files'][idx] assert extracted_file['id'] == file_.pk assert extracted_file['created'] == file_.created assert extracted_file['filename'] == file_.filename assert extracted_file['hash'] == file_.hash assert extracted_file['is_webextension'] == file_.is_webextension assert extracted_file['is_mozilla_signed_extension'] == ( file_.is_mozilla_signed_extension) assert extracted_file['is_restart_required'] == ( file_.is_restart_required) assert extracted_file['platform'] == file_.platform assert extracted_file['size'] == file_.size assert extracted_file['status'] == file_.status assert (extracted_file['webext_permissions_list'] == file_.webext_permissions_list == ['bookmarks', 'random permission'])
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.*' }) addon_factory(name='Thunderbird Polish Language Pack', type=amo.ADDON_LPAPP, target_locale='pl', file_kw={'strict_compatibility': True}, version_kw={ 'application': amo.THUNDERBIRD.id, 'min_app_version': '58.0', 'max_app_version': '58.*' }) # 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
def setUp(self): super(TestBrowseRedirect, self).setUp() self.version = version_factory(addon=addon_factory()) self.browse_redirect_url = reverse('files.browse_redirect', args=[self.version.pk])
def test_can_edit_with_discovery_edit_permission(self): addon = addon_factory() item = PromotedAddon.objects.create(addon=addon, group_id=RECOMMENDED.id) ver1 = addon.current_version ver1.update(version='1.111') ver2 = version_factory(addon=addon, version='1.222') ver3 = version_factory(addon=addon, version='1.333') item.reload() assert item.addon.current_version == ver3 approvals = [ PromotedApproval.objects.create(version=ver1, group_id=RECOMMENDED.id, application_id=amo.FIREFOX.id), PromotedApproval.objects.create(version=ver2, group_id=RECOMMENDED.id, application_id=amo.ANDROID.id), PromotedApproval.objects.create(version=ver2, group_id=LINE.id, application_id=amo.FIREFOX.id), PromotedApproval.objects.create(version=ver3, group_id=RECOMMENDED.id, application_id=amo.FIREFOX.id), ] approvals.reverse() # we order by -version_id so match it. item.reload() assert item.approved_applications detail_url = reverse(self.detail_url_name, args=(item.pk, )) user = user_factory(email='*****@*****.**') self.grant_permission(user, 'Discovery:Edit') self.client.login(email=user.email) response = self.client.get(detail_url, follow=True) assert response.status_code == 200 content = response.content.decode('utf-8') assert '1.111' in content assert '1.222' in content assert '1.333' in content response = self.client.post( detail_url, dict( self._get_approval_form(item, approvals), **self._get_heroform(''), **{ 'group_id': LINE.id, # change the group }), follow=True) assert response.status_code == 200 assert 'errors' not in response.context_data, ( response.context_data['errors']) item.reload() assert PromotedAddon.objects.count() == 1 assert item.group == LINE assert PromotedApproval.objects.count() == 4 # same # now it's not promoted because the current_version isn't approved for # LINE group assert not item.approved_applications # Try to delete one of the approvals response = self.client.post( detail_url, dict( self._get_approval_form(item, approvals), **self._get_heroform(''), **{ 'form-0-DELETE': 'on', # delete the latest approval }), follow=True) assert response.status_code == 200 assert 'errors' not in response.context_data, ( response.context_data['errors']) assert PromotedAddon.objects.count() == 1 assert PromotedApproval.objects.count() == 3 assert PrimaryHero.objects.count() == 0 # check we didn't add
def test_fetch_candidates(self): # Add nominated add-on: it should be considered. self.version.update(nomination=self.days_ago(1)) new_addon = addon_factory(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)) # Add langpack: it should also be considered. langpack = addon_factory(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 bunch of add-ons in various states that should not be returned. # Public add-on with no updates. addon_factory(file_kw={'is_webextension': True}) # Non-extension with updates. search_addon = addon_factory(type=amo.ADDON_SEARCH) version_factory(addon=search_addon, file_kw={ 'status': amo.STATUS_AWAITING_REVIEW, 'is_webextension': True }) # Disabled add-on with updates. disabled_addon = addon_factory(disabled_by_user=True) 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() 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() version_factory(addon=non_webext_addon, file_kw={'status': amo.STATUS_AWAITING_REVIEW}) # Add-on with 3 versions: # - one webext, listed, public. # - one non-listed webext version # - one listed non-webext awaiting review. complex_addon = addon_factory(file_kw={'is_webextension': True}) version_factory(addon=complex_addon, channel=amo.RELEASE_CHANNEL_UNLISTED, file_kw={'is_webextension': True}) version_factory(addon=complex_addon, file_kw={'status': amo.STATUS_AWAITING_REVIEW}) # Finally, add a second file to self.version to test the distinct(). file_factory(version=self.version, status=amo.STATUS_AWAITING_REVIEW, is_webextension=True) # Gather the candidates. command = auto_approve.Command() command.post_review = True qs = command.fetch_candidates() # 3 versions should be found. Because of the nomination date, # langpack_version should be first (its nomination date is the oldest), # followed by new_addon_version and then self.version. assert len(qs) == 3 assert qs[0] == langpack_version assert qs[1] == new_addon_version assert qs[2] == self.version
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 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(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(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(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(type=amo.ADDON_SEARCH) 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( status=amo.STATUS_NOMINATED, version_kw={ 'recommendation_approved': True, 'nomination': self.days_ago(6) }, file_kw={ 'status': amo.STATUS_AWAITING_REVIEW, 'is_webextension': True }, ) recommended_addon = version_factory(addon=addon_factory(), recommendation_approved=True, nomination=self.days_ago(7), file_kw={ 'status': amo.STATUS_AWAITING_REVIEW, 'is_webextension': True }).addon DiscoveryItem.objects.create(recommendable=True, addon=recommendable_addon_nominated) DiscoveryItem.objects.create(recommendable=True, addon=recommended_addon) # --------------------------------------------------------------------- # Add a bunch of add-ons in various states that should not be returned. # Public add-on with no updates. addon_factory(file_kw={'is_webextension': True}) # Disabled add-on with updates. disabled_addon = addon_factory(disabled_by_user=True) 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() 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() version_factory(addon=non_webext_addon, file_kw={'status': amo.STATUS_AWAITING_REVIEW}) # Add-on with 3 versions: # - one webext, listed, public. # - one non-listed webext version # - one listed non-webext awaiting review. complex_addon = addon_factory(file_kw={'is_webextension': True}) version_factory(addon=complex_addon, channel=amo.RELEASE_CHANNEL_UNLISTED, file_kw={'is_webextension': True}) version_factory(addon=complex_addon, file_kw={'status': amo.STATUS_AWAITING_REVIEW}) # Finally, 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-on with an already public version and an unlisted webext # still awaiting review complex_addon_2 = addon_factory(file_kw={'is_webextension': True}) version_factory(addon=complex_addon_2, channel=amo.RELEASE_CHANNEL_UNLISTED, file_kw={ 'is_webextension': True, 'status': amo.STATUS_AWAITING_REVIEW }) # --------------------------------------------------------------------- # Gather the candidates. command = auto_approve.Command() command.post_review = True qs = command.fetch_candidates() # 5 versions should be found. Because of the nomination date, # search_version should be first (its nomination date is the # oldest) followed etc. assert len(qs) == 7 assert [v.addon.pk for v in qs] == [ a.pk for a in ( recommended_addon, recommendable_addon_nominated, search_addon, dictionary, langpack, new_addon, self.addon, ) ]
def test_get(self): task_user = user_factory() # result labelled as "bad" because its state is TRUE_POSITIVE bad_version = version_factory(addon=addon_factory()) bad_result = ScannerResult.objects.create(scanner=YARA, version=bad_version, state=TRUE_POSITIVE) # result without a version and state is UNKNOWN ScannerResult.objects.create(scanner=YARA) # true positive, but without a version ScannerResult.objects.create(scanner=YARA, state=TRUE_POSITIVE) # result labelled as "good" because it has been approved good_version_1 = version_factory(addon=addon_factory()) good_result_1 = ScannerResult.objects.create(scanner=WAT, version=good_version_1) ActivityLog.create(amo.LOG.APPROVE_VERSION, good_version_1, user=self.user) # result labelled as "good" because auto-approve has been confirmed good_version_2 = version_factory(addon=addon_factory()) good_result_2 = ScannerResult.objects.create(scanner=CUSTOMS, version=good_version_2) ActivityLog.create(amo.LOG.APPROVE_VERSION, good_version_2, user=task_user) ActivityLog.create(amo.LOG.CONFIRM_AUTO_APPROVED, good_version_2, user=self.user) # Simulate a reviewer who has confirmed auto-approval a second time. We # should not return duplicate results. ActivityLog.create(amo.LOG.CONFIRM_AUTO_APPROVED, good_version_2, user=self.user) # result NOT labelled as "good" because action is not correct. version_3 = version_factory(addon=addon_factory()) ScannerResult.objects.create(scanner=YARA, version=version_3) ActivityLog.create(amo.LOG.REJECT_VERSION, version_3, user=self.user) # result NOT labelled as "good" because user is TASK_USER_ID version_4 = version_factory(addon=addon_factory()) ScannerResult.objects.create(scanner=YARA, version=version_4) ActivityLog.create(amo.LOG.APPROVE_VERSION, version_4, user=task_user) with override_settings(TASK_USER_ID=task_user.pk): response = self.client.get(self.url) assert response.status_code == 200 results = self.assert_json_results(response, expected_results=3) # Force a `label` value so that the serialized (expected) data is # accurate. This is needed because `label` is an annotated field # created in the QuerySet. good_result_2.label = 'good' assert results[0] == ScannerResultSerializer( instance=good_result_2).data # Force a `label` value so that the serialized (expected) data is # accurate. This is needed because `label` is an annotated field # created in the QuerySet. good_result_1.label = 'good' assert results[1] == ScannerResultSerializer( instance=good_result_1).data # Force a `label` value so that the serialized (expected) data is # accurate. This is needed because `label` is an annotated field # created in the QuerySet. bad_result.label = 'bad' assert results[2] == ScannerResultSerializer(instance=bad_result).data