This commit is contained in:
aschek 2023-11-08 10:48:34 +02:00
Родитель 2d56434545 5d40184f0f
Коммит 88a6bf2944
17 изменённых файлов: 876 добавлений и 512 удалений

Просмотреть файл

@ -488,13 +488,12 @@ workflows:
not:
equal: [ scheduled_pipeline, << pipeline.trigger_source >> ]
jobs:
- collections_serial_tests
- ratings_serial_tests
- user_serial_tests
- frontend_parallel_tests
- devhub_parallel_tests
- addon_submissions_tests
- api_submission_tests
- frontend_dev_parallel_tests
- user_dev_serial_tests
- collections_dev_serial_tests
- ratings_dev_serial_tests
- devhub_dev_parallel_tests
- addon_submissions_dev_tests
# scheduled in CircleCI Project settings to run each Wednesdays at 04:00 UTC
scheduled_coverage_run:

Просмотреть файл

@ -10,10 +10,7 @@ minimal_manifest = {
def listed_addon_minimal(uuid):
"""This holds only the strictly necessary properties required for successful submissions"""
body = {
'categories': {
'android': ['photos-media', 'shopping'],
'firefox': ['appearance', 'download-management'],
},
'categories': ['appearance', 'download-management'],
'version': {
'license': 'all-rights-reserved',
'upload': uuid,
@ -25,10 +22,7 @@ def listed_addon_minimal(uuid):
def listed_addon_details(uuid):
body = {
'categories': {
'android': ['experimental', 'performance'],
'firefox': ['bookmarks', 'privacy-security'],
},
'categories': ['bookmarks', 'privacy-security'],
'slug': 'my_sluggish_slug',
'default_locale': 'en-US',
'name': {
@ -93,10 +87,7 @@ def listed_addon_details(uuid):
edit_addon_details = {
'categories': {
'android': ['photos-media', 'shopping'],
'firefox': ['appearance', 'download-management'],
},
'categories': ['appearance', 'download-management'],
'slug': 'new_sluggish_slug',
'name': {
'de': 'DE Name edited',
@ -199,9 +190,7 @@ def new_version_details(uuid):
def lang_tool_details(uuid):
body = {
'slug': f'langpack-{reusables.get_random_string(10)}',
'categories': {
'firefox': ['general'],
},
'categories': ['general'],
'version': {'license': 'MPL-2.0', 'upload': uuid, 'compatibility': ['firefox']},
}
return body
@ -225,9 +214,7 @@ custom_license = {
def theme_details(uuid, theme_license):
body = {
"categories": {
"firefox": ['nature'],
},
"categories": ['nature'],
"summary": {
"en-US": "theme summary api submissions"
},

96
api/responses.py Normal file
Просмотреть файл

@ -0,0 +1,96 @@
abuse_report_unauthenticated_response = {
'message': 'test from the API,both',
'reporter': None,
'reporter_name': None,
'reporter_email': None,
'addon': {
'guid': '{463b483d-6150-43c9-9b52-a3d08d5ecd3a}',
'id': 1018565,
'slug': 'automation-abuse-report-add-on'
},
'addon_install_method': 'link',
'addon_install_origin': 'https://addons-server.readthedocs.io/en/latest/topics/api/abuse.html',
'addon_install_source': 'amo',
'addon_install_source_url': 'https://addons.allizom.org/en-US/firefox/addon/automation-abuse-report-add-on/',
'addon_name': 'automation-abuse-report-add-on',
'addon_signature': 'signed',
'addon_summary': 'Random summary',
'addon_version': '1.1',
'app': 'firefox',
'appversion': None,
'client_id': '06ecc8cef773a56ce40baa1ca1237184ea2c6a6a7f0485eda1ea7f4b5c317c65',
'install_date': '2023-10-10T15:00:14Z',
'lang': None,
'operating_system': 'windows',
'operating_system_version': '10',
'reason': 'settings',
'report_entry_point': 'amo',
'location': 'amo'
}
abuse_report_authenticated_response = {
"message": "test from the API,both",
"reporter": {
"id": 11688807,
"name": "api_user",
"url": "https://addons.allizom.org/en-US/firefox/user/11688807/",
"username": "anonymous-c2f376812af322105f986b81fcbb5113"
},
"reporter_name": None,
"reporter_email": None,
"addon": {
"guid": "{463b483d-6150-43c9-9b52-a3d08d5ecd3a}",
"id": 1018565,
"slug": "automation-abuse-report-add-on"
},
"addon_install_method": "link",
"addon_install_origin": "https://addons-server.readthedocs.io/en/latest/topics/api/abuse.html",
"addon_install_source": "amo",
"addon_install_source_url": "https://addons.allizom.org/en-US/firefox/addon/automation-abuse-report-add-on/",
"addon_name": "automation-abuse-report-add-on",
"addon_signature": "signed",
"addon_summary": "Random summary",
"addon_version": "1.1",
"app": "firefox",
"appversion": None,
"client_id": "06ecc8cef773a56ce40baa1ca1237184ea2c6a6a7f0485eda1ea7f4b5c317c65",
"install_date": "2023-10-10T15:00:14Z",
"lang": None,
"operating_system": "windows",
"operating_system_version": "10",
"reason": "settings",
"report_entry_point": "amo",
"location": "amo"
}
abuse_report_minimal_details = {
"message": "test from the API,both",
"reporter": None,
"reporter_name": None,
"reporter_email": None,
"addon": {
"guid": "{463b483d-6150-43c9-9b52-a3d08d5ecd3a}",
"id": 1018565,
"slug": "automation-abuse-report-add-on"
},
"addon_install_method": None,
"addon_install_origin": None,
"addon_install_source": None,
"addon_install_source_url": None,
"addon_name": None,
"addon_signature": None,
"addon_summary": None,
"addon_version": None,
"app": "firefox",
"appversion": None,
"client_id": None,
"install_date": None,
"lang": None,
"operating_system": None,
"operating_system_version": None,
"reason": None,
"report_entry_point": None,
"location": None
}

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

1
api_user.txt Normal file
Просмотреть файл

@ -0,0 +1 @@
72m7mr6v9e80uxt036m9r4qv2203w6p3

Просмотреть файл

@ -61,6 +61,5 @@ class ManageAddons(Base):
return self.find_element(*self._addon_name_locator).text
def click_addon_name(self):
self.wait.until(EC.element_to_be_clickable(self._addon_edit_link_locator))
self.find_element(*self._addon_edit_link_locator).click()
return EditAddon(self.driver, self.page.base_url).wait_for_page_to_load()

Просмотреть файл

@ -82,7 +82,7 @@ class SubmitAddon(Page):
)
_create_theme_button_locator = (By.ID, "wizardlink")
_submit_file_button_locator = (By.ID, "submit-upload-file-finish")
_addon_validation_success_locator = (By.CLASS_NAME, "bar-success")
_addon_validation_success_locator = (By.CSS_SELECTOR, "#upload-status-bar.bar-success")
_validation_fail_bar_locator = (By.CLASS_NAME, "bar-fail")
_validation_support_link_locator = (By.CSS_SELECTOR, "#upload-status-results a")
_validation_failed_message_locator = (
@ -611,14 +611,14 @@ class ListedAddonSubmissionForm(Page):
_is_experimental_checkbox_locator = (By.ID, "id_is_experimental")
_requires_payment_checkbox_locator = (By.ID, "id_requires_payment")
_categories_section_locator = (By.ID, "addon-categories-edit")
_firefox_categories_locator = (
_categories_locator = (
By.CSS_SELECTOR,
".addon-app-cats:nth-of-type(1) > ul input",
)
_android_categories_locator = (
By.CSS_SELECTOR,
".addon-app-cats:nth-of-type(2) > ul input",
)
# _android_categories_locator = (
# By.CSS_SELECTOR,
# ".addon-app-cats:nth-of-type(2) > ul input",
# )
_email_input_field_locator = (By.ID, "id_support_email_0")
_support_site_input_field_locator = (By.ID, "id_support_url_0")
_license_options_locator = (By.CLASS_NAME, "license")
@ -637,7 +637,8 @@ class ListedAddonSubmissionForm(Page):
".submission-buttons button:nth-child(2)",
)
# _theme_categories_locator = (By.CSS_SELECTOR, '#addon-categories-edit > ul input') - temporary not available
_theme_categories_locator = (By.CSS_SELECTOR, "#id_category input")
_theme_categories_locator = (By.CSS_SELECTOR, ".addon-app-cats")
_theme_category_abstract_locator = (By.CSS_SELECTOR, "#id_categories > div:nth-child(1) > label")
_theme_licence_sharing_rights_locator = (
By.CSS_SELECTOR,
"#cc-chooser ul:nth-of-type(1) input",
@ -666,6 +667,10 @@ class ListedAddonSubmissionForm(Page):
def clear_addon_name(self):
self.find_element(*self._addon_name_field_locator).clear()
@property
def theme_category_abstract(self):
return self.find_element(*self._theme_category_abstract_locator)
@property
def addon_name_field(self):
self.wait.until(
@ -717,11 +722,11 @@ class ListedAddonSubmissionForm(Page):
)
return self.find_element(*self._categories_section_locator)
def select_firefox_categories(self, count):
self.find_elements(*self._firefox_categories_locator)[count].click()
def select_categories(self, count):
self.find_elements(*self._categories_locator)[count].click()
def select_android_categories(self, count):
self.find_elements(*self._android_categories_locator)[count].click()
# def select_android_categories(self, count):
# self.find_elements(*self._android_categories_locator)[count].click()
def select_theme_categories(self, count):
self.find_elements(*self._theme_categories_locator)[count].click()
@ -929,5 +934,4 @@ class SubmissionConfirmationPage(Page):
@property
def generated_theme_preview(self):
self.wait.until(EC.visibility_of_element_located(self._theme_preview_locator))
return self.find_element(*self._theme_preview_locator)

Двоичные данные
sample-addons/make-addon.zip

Двоичный файл не отображается.

Просмотреть файл

@ -1 +1 @@
{"manifest_version": 2, "version": "3.0", "name": "EN-US Name edited"}
{"manifest_version": 2, "version": "1.0", "name": "\u028c\u0251:\u00e6\u010d\u03b2\u3041\u0147", "description": "\u263a\ufe0f\u028c\u0251:\u00e6\u010d\u03b2\u3041\u0147\u263a\ufe0f"}

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -1 +1 @@
5jrjqtiu6kyccp1ekvcbt7glbr7xvfwl
ktforx1gytxlcbxneb64clczzp8x0a9t

Просмотреть файл

@ -0,0 +1,241 @@
import json
import time
import pytest
import requests
from api import payloads, api_helpers, responses
from pages.desktop.frontend.home import Home
from scripts import reusables
# endpoints used in the post abuse report tests
_post_abuse_report = "/api/v5/abuse/report/addon/"
@pytest.mark.login("api_user")
def test_abuse_report_unauthenticated_post(base_url, selenium):
payload = payloads.abuse_report_full_body
create_abuse_report = requests.post(
url=f"{base_url}{_post_abuse_report}",
headers={
"Content-Type": "application/json"
},
data=json.dumps(payload)
)
assert (
create_abuse_report.status_code == 201
), f"Actual response: {create_abuse_report.status_code}, {create_abuse_report.text}"
assert (
create_abuse_report.json() == responses.abuse_report_unauthenticated_response
), f"Actual response: {create_abuse_report.json()}"
@pytest.mark.create_session("api_user")
def test_abuse_report_authenticated(base_url, selenium, session_auth):
payload = payloads.abuse_report_full_body
create_abuse_report = requests.post(
url=f"{base_url}{_post_abuse_report}",
headers={
"Content-Type": "application/json",
"Authorization": f"Session {session_auth}"
},
data=json.dumps(payload)
)
assert (
create_abuse_report.status_code == 201
), f"Actual response: {create_abuse_report.status_code}, {create_abuse_report.text}"
assert (
create_abuse_report.json() == responses.abuse_report_authenticated_response
), f"Actual response: {create_abuse_report.json()}"
def test_abuse_report_minimal_details(base_url, selenium):
payload = {
"addon": "{463b483d-6150-43c9-9b52-a3d08d5ecd3a}",
"message": "test from the API,both"
}
create_abuse_report = requests.post(
url=f"{base_url}{_post_abuse_report}",
headers={
"Content-Type": "application/json"
},
data=json.dumps(payload)
)
assert (
create_abuse_report.status_code == 201
), f"Actual response: {create_abuse_report.status_code}, {create_abuse_report.text}";
assert (
create_abuse_report.json() == responses.abuse_report_minimal_details
), f"Actual response: {create_abuse_report.json()}"
@pytest.mark.parametrize(
"addon_install_method",
[
"link",
"random_text"
],
ids=[
'Accepted value: link',
'Unsupported value: random_text'
]
)
def test_addon_install_method_parameter(base_url, selenium, addon_install_method):
payload = payloads.abuse_report_body(f"{addon_install_method}", "amo", "settings", "signed", "menu", "amo")
create_abuse_report = requests.post(
url=f"{base_url}{_post_abuse_report}",
headers={
"Content-Type": "application/json"
},
data=json.dumps(payload)
)
assert (
create_abuse_report.status_code == 201
), f"Actual response: {create_abuse_report.status_code}, {create_abuse_report.text}";
assert (
create_abuse_report.json()["addon_install_method"] == addon_install_method
), f"Actual response: {create_abuse_report.json()}"
@pytest.mark.parametrize(
"addon_install_source",
[
"amo",
"random_text"
],
ids=[
'Accepted value: amo',
'Unsupported value: random_text'
]
)
def test_addon_install_source_parameter(base_url, selenium, addon_install_source):
payload = payloads.abuse_report_body("link", f"{addon_install_source}", "settings", "signed", "menu", "amo")
create_abuse_report = requests.post(
url=f"{base_url}{_post_abuse_report}",
headers={
"Content-Type": "application/json"
},
data=json.dumps(payload)
)
assert (
create_abuse_report.status_code == 201
), f"Actual response: {create_abuse_report.status_code}, {create_abuse_report.text}";
assert (
create_abuse_report.json()["addon_install_method"] == addon_install_source
), f"Actual response: {create_abuse_report.json()}"
@pytest.mark.parametrize(
"reason",
[
"damage",
"random_text"
],
ids=[
'Accepted value: damage',
'Unsupported value: random_text'
]
)
def test_reason_parameter(base_url, selenium, reason):
payload = payloads.abuse_report_body("link", "amo", f"{reason}", "signed", "menu", "amo")
create_abuse_report = requests.post(
url=f"{base_url}{_post_abuse_report}",
headers={
"Content-Type": "application/json"
},
data=json.dumps(payload)
)
assert (
create_abuse_report.status_code == 201
), f"Actual response: {create_abuse_report.status_code}, {create_abuse_report.text}";
assert (
create_abuse_report.json()["addon_install_method"] == reason
), f"Actual response: {create_abuse_report.json()}"
@pytest.mark.parametrize(
"addon_signature",
[
"curated_and_partner",
"random_text"
],
ids=[
'Accepted value: curated_and_partner',
'Unsupported value: random_text'
]
)
def test_addon_signature_parameter(base_url, selenium, addon_signature):
payload = payloads.abuse_report_body("installtrigger", "about_preferences", "broken", f"{addon_signature}",
"uninstall", "addon")
create_abuse_report = requests.post(
url=f"{base_url}{_post_abuse_report}",
headers={
"Content-Type": "application/json"
},
data=json.dumps(payload)
)
assert (
create_abuse_report.status_code == 201
), f"Actual response: {create_abuse_report.status_code}, {create_abuse_report.text}";
assert (
create_abuse_report.json()["addon_install_method"] == addon_signature
), f"Actual response: {create_abuse_report.json()}"
@pytest.mark.parametrize(
"report_entry_point",
[
"unified_context_menu",
"random_text"
],
ids=[
'Accepted value: unified_context_menu',
'Unsupported value: random_text'
]
)
def test_report_entry_point_parameter(base_url, selenium, report_entry_point):
payload = payloads.abuse_report_body("drag_and_drop", "app_profile", "policy", "preliminary",
f"{report_entry_point}", "addon")
create_abuse_report = requests.post(
url=f"{base_url}{_post_abuse_report}",
headers={
"Content-Type": "application/json"
},
data=json.dumps(payload)
)
assert (
create_abuse_report.status_code == 201
), f"Actual response: {create_abuse_report.status_code}, {create_abuse_report.text}";
assert (
create_abuse_report.json()["addon_install_method"] == report_entry_point
), f"Actual response: {create_abuse_report.json()}"
@pytest.mark.parametrize(
"location",
[
"both",
"random_text"
],
ids=[
'Accepted value: both',
'Unsupported value: random_text'
]
)
def test_location_parameter(base_url, selenium, location):
payload = payloads.abuse_report_body("link", "amo", "settings", "signed", "menu", f"{location}")
create_abuse_report = requests.post(
url=f"{base_url}{_post_abuse_report}",
headers={
"Content-Type": "application/json"
},
data=json.dumps(payload)
)
assert (
create_abuse_report.status_code == 201
), f"Actual response: {create_abuse_report.status_code}, {create_abuse_report.text}";
assert (
create_abuse_report.json()["addon_install_method"] == location
), f"Actual response: {create_abuse_report.json()}"

Просмотреть файл

@ -81,7 +81,7 @@ def test_edit_listed_addon_details(base_url, session_auth):
@pytest.mark.serial
@pytest.mark.create_session("api_user")
def test_extension_add_invalid_android_categories(base_url, session_auth):
def test_extension_add_invalid_categories(base_url, session_auth):
"""Try to upload an addon that has invalid android categories set in the JSON payload"""
with open("sample-addons/listed-addon.zip", "rb") as file:
upload = requests.post(
@ -96,12 +96,12 @@ def test_extension_add_invalid_android_categories(base_url, session_auth):
print(upload.json())
# get the addon uuid generated after upload
uuid = upload.json()["uuid"]
invalid_android_catg = ["nature", "privacy-security", "", 123, None]
invalid_android_catg = ["", 123, None]
for item in invalid_android_catg:
payload = {
**payloads.listed_addon_details(uuid),
"categories": {"android": [item], "firefox": ["bookmarks"]},
"slug": "invalid-android-cat",
"categories": [item],
"slug": "invalid-cat",
}
create_addon = requests.post(
url=f"{base_url}{_addon_create}",
@ -121,6 +121,47 @@ def test_extension_add_invalid_android_categories(base_url, session_auth):
"Invalid category name" in create_addon.text
), f"Actual response message was {create_addon.text}"
@pytest.mark.serial
@pytest.mark.create_session("api_user")
def test_extension_one_category_and_other_category(base_url, session_auth):
"""Try to upload an addon that has invalid android categories set in the JSON payload"""
with open("sample-addons/listed-addon.zip", "rb") as file:
upload = requests.post(
url=f"{base_url}{_upload}",
headers={"Authorization": f"Session {session_auth}"},
files={"upload": file},
data={"channel": "listed"},
)
upload.raise_for_status()
# sleep to allow the first request to be processed
time.sleep(3)
print(upload.json())
# get the addon uuid generated after upload
uuid = upload.json()["uuid"]
invalid_android_catg = ["Appearance"]
for item in invalid_android_catg:
payload = {
**payloads.listed_addon_details(uuid),
"categories": ["Other", item],
"slug": "invalid-cat",
}
create_addon = requests.post(
url=f"{base_url}{_addon_create}",
headers={
"Authorization": f"Session {session_auth}",
"Content-Type": "application/json",
},
data=json.dumps(payload),
)
print(
f'For android category "{item}": Response status is {create_addon.status_code}; {create_addon.text}\n'
)
assert (
create_addon.status_code == 400
), f"Actual status code was {create_addon.status_code}"
assert (
"Invalid category name" in create_addon.text
), f"Actual response message was {create_addon.text}"
@pytest.mark.serial
@pytest.mark.create_session("api_user")

Просмотреть файл

@ -83,7 +83,7 @@ def firefox_options(firefox_options, base_url, variables):
firefox_options.set_preference(
"extensions.update.url", variables["extensions_update_url"]
)
firefox_options.add_argument("-headless")
firefox_options.add_argument("-foreground")
firefox_options.log.level = "trace"
return firefox_options

Просмотреть файл

@ -24,7 +24,7 @@ def submit_addon_method(selenium, base_url):
summary = reusables.get_random_string(10)
confirmation_page.set_addon_name(random_string)
confirmation_page.set_addon_summary(summary)
confirmation_page.select_firefox_categories(1)
confirmation_page.select_categories(1)
confirmation_page.select_license_options[0].click()
confirmation_page.submit_addon()
return f"listed-addon{random_string}"
@ -138,7 +138,7 @@ def test_disable_an_addon_at_submission_tc_id_c1898098(selenium, base_url, wait,
listed_addon_submission_form.clear_addon_name()
listed_addon_submission_form.set_addon_name(random_string)
listed_addon_submission_form.set_addon_summary(summary)
listed_addon_submission_form.select_firefox_categories(1)
listed_addon_submission_form.select_categories(1)
listed_addon_submission_form.select_license_options[0].click()
"""Complete the form and "Submit Version"""
listed_addon_submission_form.submit_addon()

Просмотреть файл

@ -91,7 +91,7 @@ def test_submit_listed_wizard_theme_tc_id_c97500(selenium, base_url, variables,
assert theme_name in theme_details.addon_name_field.get_attribute("value")
theme_details.set_addon_summary("Theme summary")
# select a category for the theme
theme_details.select_theme_categories(0)
theme_details.theme_category_abstract.click()
# set up a license for the theme based on 'Yes'[0]/'No'[1] options
theme_details.select_theme_licence_sharing_rights(1)
theme_details.select_theme_license_commercial_use(1)
@ -251,8 +251,8 @@ def test_submit_listed_addon_tc_id_c4369(selenium, base_url, variables, wait):
details_form.requires_payment.click()
# reusables.scroll_into_view(selenium, details_form.categories_section)
# set Firefox and Android categories for the addon
details_form.select_firefox_categories(0)
details_form.select_android_categories(0)
details_form.select_categories(0)
# details_form.select_android_categories(0)
details_form.email_input_field("some-mail@mail.com")
details_form.support_site_input_field("https://example.com")
# set an addon license from the available list
@ -306,8 +306,8 @@ def test_submit_addon_3mb_size_tc_id_c2274214(selenium, base_url, wait, variable
details_form.requires_payment.click()
# reusables.scroll_into_view(selenium, details_form.categories_section)
# set Firefox and Android categories for the addon
details_form.select_firefox_categories(0)
details_form.select_android_categories(0)
details_form.select_categories(0)
# details_form.select_android_categories(0)
details_form.email_input_field("some-mail@mail.com")
details_form.support_site_input_field("https://example.com")
# set an addon license from the available list
@ -448,7 +448,7 @@ def test_submit_unicode_addon_tc_id_c4590(
source = submit_addon.click_continue_upload_button()
source.select_no_to_omit_source()
details_form = source.continue_listed_submission()
details_form.select_firefox_categories(0)
details_form.select_categories(0)
# set an addon license from the available list
details_form.select_license_options[0].click()
# submit the add-on details

Просмотреть файл

@ -8,7 +8,7 @@ from pages.desktop.frontend.static_pages import StaticPages
@pytest.mark.nondestructive
@pytest.mark.xfail(
reason="There is an issue with search on stage - #16610", strict=False
reason="There is an issue with search on stage-#16610", strict=False
)
def test_about_firefox_addons_page_links(base_url, selenium, variables):
Home(selenium, base_url).open().wait_for_page_to_load()