diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml index 64c80032f..967559896 100644 --- a/.github/workflows/static-analysis.yml +++ b/.github/workflows/static-analysis.yml @@ -34,11 +34,16 @@ jobs: name: Ruff runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - uses: chartboost/ruff-action@v1 + - name: Checkout + uses: actions/checkout@v4 + - name: Lint + uses: chartboost/ruff-action@v1 with: args: check --output-format=github - src: './src' + - name: Format + uses: chartboost/ruff-action@v1 + with: + args: format --check sonarcloud: name: Sonar cloud diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b8be43dda..2f9127d19 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -13,7 +13,7 @@ repos: files: requirements-(base|production).in args: [requirements/source/requirements-production.in, "--output-file", requirements/generated/requirements-production.txt] - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.5.4 + rev: v0.6.2 hooks: - id: ruff args: [ --fix ] diff --git a/app/__init__.py b/app/__init__.py index 19d57ea26..940c3f5dd 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -133,9 +133,7 @@ def create_app(config_class=Config): ) # Concat all headscripts seperately so they can be loaded into the DOM head. headscripts = Bundle( - "src/js/headscripts/*.js", - filters="jsmin", - output="dist/js/headscripts.min.js" + "src/js/headscripts/*.js", filters="jsmin", output="dist/js/headscripts.min.js" ) if "css" not in assets: assets.register("css", css) diff --git a/app/main/__init__.py b/app/main/__init__.py index e822fdf02..9457df33b 100644 --- a/app/main/__init__.py +++ b/app/main/__init__.py @@ -3,4 +3,4 @@ bp = Blueprint("main", __name__, template_folder="../templates/main") from app.main import routes # noqa: E402,F401 -from app.main import filters +from app.main import filters # noqa: E402,F401 diff --git a/app/main/filters.py b/app/main/filters.py index ae74cba93..28a6094ec 100644 --- a/app/main/filters.py +++ b/app/main/filters.py @@ -4,7 +4,7 @@ @bp.app_template_filter("dict") def str_to_dict(s): - """ Uses the JSON module to parse a string into a dict. + """Uses the JSON module to parse a string into a dict. This can be invoked in Jinja templates using: {{ '{"spam": "eggs"}' | dict }} @@ -16,7 +16,7 @@ def str_to_dict(s): @bp.app_template_filter("get_item") def get_item_from_dict(d, s): - """ Gets an item from a dict safely returning None if it is not present + """Gets an item from a dict safely returning None if it is not present This can be invoked in Jinja templates using: {{ '{"spam": "eggs"}' | dict | get_item("spam") }} diff --git a/app/main/gtm.py b/app/main/gtm.py index d03a2ce95..08d16530e 100644 --- a/app/main/gtm.py +++ b/app/main/gtm.py @@ -33,5 +33,7 @@ def detect_gtm_anon_id(): def remember_gtm_anon_id(response): session["gtm_anon_id"] = str(uuid.uuid4()) expiration_date = datetime.now(UTC) + timedelta(days=30) - response.set_cookie("gtm_anon_id", session.get("gtm_anon_id"), expires=expiration_date) + response.set_cookie( + "gtm_anon_id", session.get("gtm_anon_id"), expires=expiration_date + ) return response diff --git a/requirements/generated/requirements-development.txt b/requirements/generated/requirements-development.txt index 535b8bb58..ccaa68447 100644 --- a/requirements/generated/requirements-development.txt +++ b/requirements/generated/requirements-development.txt @@ -124,7 +124,7 @@ requests==2.32.3 # pytest-base-url rich==13.7.1 # via flask-limiter -ruff==0.5.4 +ruff==0.6.2 # via -r requirements/source/requirements-development.in sentry-sdk[flask]==2.10.0 # via -r requirements/source/requirements-base.in diff --git a/tests/functional_tests/conftest.py b/tests/functional_tests/conftest.py index bf0c55301..7288e8ab5 100644 --- a/tests/functional_tests/conftest.py +++ b/tests/functional_tests/conftest.py @@ -3,6 +3,7 @@ from app import create_app from flask import url_for + class TestConfig(Config): TESTING = True DEBUG = True @@ -10,6 +11,7 @@ class TestConfig(Config): RATELIMIT_ENABLED = False SECRET_KEY = "TEST_KEY" + @pytest.fixture(scope="session") def app(): app = create_app(TestConfig) @@ -28,4 +30,4 @@ def runner(app): @pytest.fixture(scope="function", autouse=True) def startup(app, page): - page.goto(url_for('main.index', _external=True)) \ No newline at end of file + page.goto(url_for("main.index", _external=True)) diff --git a/tests/functional_tests/test_accessibility.py b/tests/functional_tests/test_accessibility.py index b29016fc4..dab44d256 100644 --- a/tests/functional_tests/test_accessibility.py +++ b/tests/functional_tests/test_accessibility.py @@ -8,12 +8,13 @@ ACCESSIBILITY_STANDARDS = ["wcag2a", "wcag2aa"] + def check_accessibility(page: Page): - ''' + """ Inserts axe core python into a page at the yield step to run accessibility based testing. Axe will run on the page defined in the function. - ''' + """ if page.title() != "localhost": directory = "tests/functional_tests/accessibility_output" if not os.path.exists(directory): @@ -24,16 +25,16 @@ def check_accessibility(page: Page): wcag_violations = [] - for violation in results['violations']: + for violation in results["violations"]: if set(violation["tags"]) & set(ACCESSIBILITY_STANDARDS): wcag_violations.append(violation) - + if len(wcag_violations) == 0: assert "No WCAG accessibility issues found" else: # Cleans the URL to remove any invalid characters and replace with _ invalid_filename_chars = r'[\/:*?"<>|]' - sanitized_title = re.sub(invalid_filename_chars, '_', page.title()) + sanitized_title = re.sub(invalid_filename_chars, "_", page.title()) max_title_len = 30 file_name = f"axe_results_{sanitized_title[:max_title_len]}.json" @@ -44,7 +45,7 @@ def check_accessibility(page: Page): @pytest.mark.usefixtures("live_server") def test_all_page_accessibility(app, page: Page): - ignored_routes = ['static', '/'] + ignored_routes = ["static", "/"] routes = app.view_functions for route in routes: if route not in ignored_routes: @@ -52,9 +53,10 @@ def test_all_page_accessibility(app, page: Page): page.goto(full_url) check_accessibility(page) + def test_accessibility_folder(): - path = 'tests/functional_tests/accessibility_output' + path = "tests/functional_tests/accessibility_output" if not any(os.scandir(path)): assert True else: - assert not 'WCAG accessibility issues found' \ No newline at end of file + assert not "WCAG accessibility issues found" diff --git a/tests/functional_tests/test_example.py b/tests/functional_tests/test_example.py index 7538e9188..8cf00d6a6 100644 --- a/tests/functional_tests/test_example.py +++ b/tests/functional_tests/test_example.py @@ -1,6 +1,7 @@ from playwright.sync_api import Page import pytest + @pytest.mark.usefixtures("live_server") def test_base_accessibility(page: Page): - pass \ No newline at end of file + pass diff --git a/tests/unit_tests/test_example.py b/tests/unit_tests/test_example.py index 415b80a38..02dbb2a90 100644 --- a/tests/unit_tests/test_example.py +++ b/tests/unit_tests/test_example.py @@ -1,4 +1,4 @@ def test_coverage(): # Test Pytest coverage assert 1 + 1 == 2 - pass \ No newline at end of file + pass