diff --git a/locales/en/LC_MESSAGES/js_linting.mo b/locales/en/LC_MESSAGES/js_linting.mo new file mode 100644 index 00000000..aaac9d32 Binary files /dev/null and b/locales/en/LC_MESSAGES/js_linting.mo differ diff --git a/locales/en/LC_MESSAGES/js_linting.po b/locales/en/LC_MESSAGES/js_linting.po new file mode 100644 index 00000000..bcd436cb --- /dev/null +++ b/locales/en/LC_MESSAGES/js_linting.po @@ -0,0 +1,42 @@ +# English (default). +# Copyright (C) 2025 WebPerf +# FIRST AUTHOR , 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-02-28 20:18+0200\n" +"PO-Revision-Date: 2025-02-28 20:18+0200\n" +"Last-Translator: cockroacher \n" +"Language-Team: English \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: pygettext.py 1.5\n" + +msgid "TEXT_RUNNING_TEST" +msgstr "## Test: 27 - JS\n" + +msgid "TEXT_REVIEW_JS_VERY_GOOD" +msgstr "- The JS is very good.\n" + +msgid "TEXT_REVIEW_JS_IS_GOOD" +msgstr "- The JS is good.\n" + +msgid "TEXT_REVIEW_JS_IS_OK" +msgstr "- The JS is neither good or bad.\n" + +msgid "TEXT_REVIEW_JS_IS_BAD" +msgstr "- The JS is bad.\n" + +msgid "TEXT_REVIEW_JS_IS_VERY_BAD" +msgstr "- The JS is very bad.\n" + +msgid "TEXT_REVIEW_ERRORS_ITEM" +msgstr " - {0} (number of errors of this type: {1})\n" + +msgid "TEXT_REVIEW_RATING_GROUPED" +msgstr ", number of grouped error type: {0}" + +msgid "TEXT_REVIEW_RATING_ITEMS" +msgstr ", number of errors: {0}" diff --git a/locales/gov/LC_MESSAGES/js_linting.mo b/locales/gov/LC_MESSAGES/js_linting.mo new file mode 100644 index 00000000..aaac9d32 Binary files /dev/null and b/locales/gov/LC_MESSAGES/js_linting.mo differ diff --git a/locales/gov/LC_MESSAGES/js_linting.po b/locales/gov/LC_MESSAGES/js_linting.po new file mode 100644 index 00000000..bcd436cb --- /dev/null +++ b/locales/gov/LC_MESSAGES/js_linting.po @@ -0,0 +1,42 @@ +# English (default). +# Copyright (C) 2025 WebPerf +# FIRST AUTHOR , 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-02-28 20:18+0200\n" +"PO-Revision-Date: 2025-02-28 20:18+0200\n" +"Last-Translator: cockroacher \n" +"Language-Team: English \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: pygettext.py 1.5\n" + +msgid "TEXT_RUNNING_TEST" +msgstr "## Test: 27 - JS\n" + +msgid "TEXT_REVIEW_JS_VERY_GOOD" +msgstr "- The JS is very good.\n" + +msgid "TEXT_REVIEW_JS_IS_GOOD" +msgstr "- The JS is good.\n" + +msgid "TEXT_REVIEW_JS_IS_OK" +msgstr "- The JS is neither good or bad.\n" + +msgid "TEXT_REVIEW_JS_IS_BAD" +msgstr "- The JS is bad.\n" + +msgid "TEXT_REVIEW_JS_IS_VERY_BAD" +msgstr "- The JS is very bad.\n" + +msgid "TEXT_REVIEW_ERRORS_ITEM" +msgstr " - {0} (number of errors of this type: {1})\n" + +msgid "TEXT_REVIEW_RATING_GROUPED" +msgstr ", number of grouped error type: {0}" + +msgid "TEXT_REVIEW_RATING_ITEMS" +msgstr ", number of errors: {0}" diff --git a/locales/sv/LC_MESSAGES/js_linting.mo b/locales/sv/LC_MESSAGES/js_linting.mo new file mode 100644 index 00000000..58ae861f Binary files /dev/null and b/locales/sv/LC_MESSAGES/js_linting.mo differ diff --git a/locales/sv/LC_MESSAGES/js_linting.po b/locales/sv/LC_MESSAGES/js_linting.po new file mode 100644 index 00000000..d1c04b89 --- /dev/null +++ b/locales/sv/LC_MESSAGES/js_linting.po @@ -0,0 +1,42 @@ +# Swedish +# Copyright (C) 2025 WebPerf +# FIRST AUTHOR , 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-02-28 20:18+0200\n" +"PO-Revision-Date: 2025-02-28 20:18+0200\n" +"Last-Translator: cockroacher \n" +"Language-Team: Swedish \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: pygettext.py 1.5\n" + +msgid "TEXT_RUNNING_TEST" +msgstr "## Test: 27 - JS\n" + +msgid "TEXT_REVIEW_JS_VERY_GOOD" +msgstr "- JS är välbyggd!\n" + +msgid "TEXT_REVIEW_JS_IS_GOOD" +msgstr "- JS är bra.\n" + +msgid "TEXT_REVIEW_JS_IS_OK" +msgstr "- JS är ok.\n" + +msgid "TEXT_REVIEW_JS_IS_BAD" +msgstr "- JS är dålig.\n" + +msgid "TEXT_REVIEW_JS_IS_VERY_BAD" +msgstr "- JS är väldigt dålig.\n" + +msgid "TEXT_REVIEW_ERRORS_ITEM" +msgstr " - {0} (totalt {1} st)\n" + +msgid "TEXT_REVIEW_RATING_GROUPED" +msgstr ", antal grupperade fel: {0}" + +msgid "TEXT_REVIEW_RATING_ITEMS" +msgstr ", antal fel: {0}" diff --git a/tests/js_linting.py b/tests/js_linting.py new file mode 100644 index 00000000..de5ae59d --- /dev/null +++ b/tests/js_linting.py @@ -0,0 +1,450 @@ +# -*- coding: utf-8 -*- +from datetime import datetime +import json +import os +from pathlib import Path +import re +import urllib +from bs4 import BeautifulSoup +from helpers.models import Rating +from helpers.setting_helper import get_config +from tests.utils import get_friendly_url_name, get_translation, set_cache_file +from tests.lint_base import calculate_rating, get_data_for_url,\ + get_error_review, get_error_types_review,\ + get_errors_for_url, get_rating, get_reviews_from_errors + +# DEFAULTS +GROUP_ERROR_MSG_REGEX = r"(\"[^\"]+\")" +FIRST_USED_AT_LINE_REGEX = r", first used at line [0-9]+" + +def run_test(global_translation, url): + """ + Only work on a domain-level. Returns tuple with decimal for grade and string with review + """ + + local_translation = get_translation('js_linting', get_config('general.language')) + + print(local_translation('TEXT_RUNNING_TEST')) + + print(global_translation('TEXT_TEST_START').format( + datetime.now().strftime('%Y-%m-%d %H:%M:%S'))) + + rating = Rating(global_translation, get_config('general.review.improve-only')) + data = get_data_for_url(url) + if data is None: + rating.overall_review = global_translation('TEXT_SITE_UNAVAILABLE') + return (rating, {'failed': True }) + + all_script_resources = [] + + result_dict = { + 'has_script_elements': False, + 'has_script_files': False, + 'errors': { + 'all': [], + 'script_element': [], + 'script_files': [] + }, + 'sources': [] + } + + for html_entry in data['htmls']: + tmp_all_script_resources, tmp_rating = handle_html_markup_entry( + html_entry, + global_translation, + url, + local_translation, + result_dict) + rating += tmp_rating + all_script_resources.extend(tmp_all_script_resources) + + for resource_url in all_script_resources: + for entry in data['all']: + if resource_url == entry['url']: + result_dict['sources'].append({ + 'url': resource_url, + 'index': entry['index'] + }) + + for script_resource in all_script_resources: + data_resource_info_to_remove = None + for data_resource_info in data['resources']: + if data_resource_info['url'] == script_resource: + data_resource_info_to_remove = data_resource_info + break + if data_resource_info_to_remove is not None: + data['resources'].remove(data_resource_info_to_remove) + + rating += rate_js( + global_translation, + local_translation, + data, + result_dict) + + points = rating.get_overall() + + review = '' + if points >= 5.0: + review = local_translation('TEXT_REVIEW_JS_VERY_GOOD') + elif points >= 4.0: + review = local_translation('TEXT_REVIEW_JS_IS_GOOD') + elif points >= 3.0: + review = local_translation('TEXT_REVIEW_JS_IS_OK') + elif points > 1.0: + review = local_translation('TEXT_REVIEW_JS_IS_BAD') + elif points <= 1.0: + review = local_translation('TEXT_REVIEW_JS_IS_VERY_BAD') + + rating.overall_review = review + + print(global_translation('TEXT_TEST_END').format( + datetime.now().strftime('%Y-%m-%d %H:%M:%S'))) + + return (rating, result_dict) + +def handle_html_markup_entry(entry, global_translation, url, local_translation, result_dict): + """ + Handles an entry in the webpage data, checks for JS related errors and rates them. + + Parameters: + entry (dict): The entry in the webpage data to handle. + global_translation (function): Function to translate text globally. + url (str): The URL of the webpage. + local_translation (function): Function to translate text locally. + result_dict (dict): Dictionary containing results of previous checks. + + Returns: + list: All script resources found in the entry. + Rating: The rating after evaluating the JS related errors in the entry. + """ + all_script_resources = [] + rating = Rating(global_translation, get_config('general.review.improve-only')) + req_url = entry['url'] + name = get_friendly_url_name(global_translation, req_url, entry['index']) + html = entry['content'] + (elements, errors) = get_errors_for_script_tags(req_url, html) + if len(elements) > 0: + result_dict['has_script_elements'] = True + result_dict['errors']['all'].extend(errors) + result_dict['errors']['script_element'].extend(errors) + rating += create_review_and_rating( + errors, + global_translation, + local_translation, + f'- `