Skip to content

fix lint - #3

Open
MilenaChowaniec wants to merge 33 commits into
Problematy:mainfrom
MilenaChowaniec:addedUnitTest
Open

fix lint#3
MilenaChowaniec wants to merge 33 commits into
Problematy:mainfrom
MilenaChowaniec:addedUnitTest

Conversation

@MilenaChowaniec

@MilenaChowaniec MilenaChowaniec commented Jul 31, 2025

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • Style

    • Improved code formatting and consistency across the plugin (imports, string quotes, indentation, inline comments, and embedded HTML/CSS/JS).
  • Documentation

    • Corrected plugin package name and configuration example in README.
  • Bug Fixes

    • Updated unit test expectation for HTTP response status.
  • Chores

    • Consolidated and improved CI e2e testing flow and test server startup; adjusted test runner wait times and test host.
  • New Features (Tests)

    • Added e2e test app, config, and fixture data; updated Cypress base URL.

@coderabbitai

coderabbitai Bot commented Jul 31, 2025

Copy link
Copy Markdown

Walkthrough

Added end-to-end test scaffolding and CI changes, corrected README plugin naming, made stylistic formatting tweaks in platzky_b4uleave/entrypoint.py, adjusted a unit test expectation from 200 to 404, and updated Cypress baseUrl. New files provide an app factory, e2e config, and test fixture data; workflow now starts Flask with an app factory and runs Cypress from the e2e tests directory.

Changes

Cohort / File(s) Change Summary
Plugin entrypoint (styling)
platzky_b4uleave/entrypoint.py
Removed unused import, reformatted process signature and multiline HTML injection, standardized quotes; no logic change.
Documentation
README.md
Fixed package/install name and plugin name in example from "platzky-b4uLeave"/"b4uLeave" to "platzky-b4uleave"/"b4uleave".
Unit test
tests/unit_tests/test_b4uleave.py
Updated expected HTTP response status from 200 to 404; other assertions unchanged.
E2E test app
tests/e2e_tests/e2e_app.py
Added create_app(config_path: str) factory that registers a root route rendering a static test HTML page.
E2E fixtures / config / data
tests/e2e_tests/e2e_test_config.yml, tests/e2e_tests/e2e_test_data.json
Added YAML config and JSON data fixture for e2e tests (app settings, DB path, languages, feature flags, sample places, site_content, plugin config).
Cypress config
tests/e2e_tests/cypress.config.js
Changed baseUrl from http://www.goodmap.localhost:5000/ to http://localhost:5000/.
CI workflow
.github/workflows/tests.yml
Reworked e2e flow to start Flask via CLI with an app factory and config file, run Cypress from tests/e2e_tests, increased server wait, removed separate start/stop and coverage steps.

Sequence Diagram(s)

sequenceDiagram
    participant CI as CI Job
    participant Cypress as Cypress Runner
    participant FlaskCLI as flask --app create_app(...)
    participant App as Flask App
    participant Plugin as b4uleave after_request

    CI->>FlaskCLI: start Flask using app factory (create_app(config_path))
    activate FlaskCLI
    FlaskCLI->>App: initialize app (register routes)
    App->>App: root route serves static HTML
    CI->>Cypress: run tests (npx cypress run) against baseUrl
    Cypress->>App: GET /
    App->>Plugin: after_request -> may inject modal HTML (if enabled)
    Plugin-->>App: modified HTML response
    App-->>Cypress: 200/404 response with content
    deactivate FlaskCLI
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

  • this should not be necessary argument goodmap#211 — The e2e test config file includes the same LANGUAGES section and the "TODO this should not be necessary argument" comment; this PR's addition of tests/e2e_tests/e2e_test_config.yml appears to address that area.

Possibly related PRs

  • Added unit test and improved plugin code #2 — Touches the same plugin entrypoint (platzky_b4uleave/entrypoint.py) and tests; likely the initial implementation that this PR updates.
  • (no other strong code-level matches found)

Poem

A rabbit hopped through code today,
Pushed fixtures, tests, and docs to play.
A tiny app factory sprang to life,
CI hummed, Cypress danced—no strife.
🐇✨

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
platzky_b4uleave/entrypoint.py (2)

1-7: Expose Flask only for typing via TYPE_CHECKING.

app is an opaque positional parameter right now. Importing the Flask class only inside a typing.TYPE_CHECKING guard gives IDE/introspection benefits without adding a hard runtime dependency (and keeps the linter happy since you removed the unused import).

-from flask import Response
+from flask import Response
+from typing import TYPE_CHECKING
+
+if TYPE_CHECKING:  # pragma: no cover
+    from flask import Flask       # noqa: F401  (import used only for type-checking)

…and then annotate the first argument:

-def process(
-    app, plugin_config: Dict[str, Any]
+def process(
+    app: "Flask", plugin_config: Dict[str, Any]

17-22: Micro-optimisation: cache compiled HTML once.

add_B4ULeave rebuilds the giant HTML/JS snippet on every request.
Build it once outside the handler (after message/stay/leave are known) and reuse; this cuts down string formatting and reduces per-request overhead.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8a7beae and 10f6fd8.

📒 Files selected for processing (1)
  • platzky_b4uleave/entrypoint.py (2 hunks)

Comment on lines +11 to 16
message = app.config["b4uleave"].get(
"message", "Czy na pewno chcesz<br>opuścić naszą stronę?"
)
stay = app.config["b4uleave"].get("stay", "Stay")
leave = app.config["b4uleave"].get("leave", "Leave")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Unsanitised user-controlled HTML ⇒ reflected-XSS vector.

message, stay, and leave come straight from plugin_config and are interpolated into the DOM without escaping.
An attacker configuring the plugin (or compromising the config source) can inject arbitrary scripts.

-import ...
+import html  # at top

 ...
-message = app.config["b4uleave"].get(
-    "message", "Czy na pewno chcesz<br>opuścić naszą stronę?"
-)
-stay = app.config["b4uleave"].get("stay", "Stay")
-leave = app.config["b4uleave"].get("leave", "Leave")
+cfg      = app.config["b4uleave"]
+message  = html.escape(cfg.get("message", "Czy na pewno chcesz<br>opuścić naszą stronę?"), quote=True)
+stay     = html.escape(cfg.get("stay",   "Stay"),  quote=True)
+leave    = html.escape(cfg.get("leave",  "Leave"), quote=True)

If you intentionally allow HTML in message, use flask.Markup to whitelist only that field and still escape the others.

Also applies to: 69-73

🤖 Prompt for AI Agents
In platzky_b4uleave/entrypoint.py around lines 11 to 16, the variables message,
stay, and leave are taken directly from the config and inserted into the DOM
without escaping, creating a reflected XSS risk. To fix this, apply proper
escaping to stay and leave to prevent script injection, and if HTML is
intentionally allowed in message, wrap it with flask.Markup to safely mark it as
trusted HTML. Also apply the same escaping and marking approach to the similar
code at lines 69 to 73.

Comment on lines +115 to +116
)
return response

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

"</body>" string replace is brittle; use a real parser.

replace("</body>", html + "</body>")
• fails for <BODY> / mixed-case tags,
• injects nothing if the tag is missing,
• may break when the string appears inside a <script> or <textarea>.

Consider BeautifulSoup or lxml.html for robust insertion:

from bs4 import BeautifulSoup

soup = BeautifulSoup(response.get_data(as_text=True), "html.parser")
if soup.body:
    soup.body.append(BeautifulSoup(html, "html.parser"))
    response.set_data(str(soup))

At minimum, perform a case-insensitive search and fall back gracefully.

🤖 Prompt for AI Agents
In platzky_b4uleave/entrypoint.py around lines 115 to 116, the code uses a
brittle string replace to insert HTML before the closing </body> tag, which
fails with case variations, missing tags, or when the string appears inside
scripts. Replace this with a robust HTML parser like BeautifulSoup: parse the
response data, check for the body tag, append the new HTML safely, and then set
the modified HTML back to the response. This ensures correct insertion
regardless of tag case or content structure.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
.github/workflows/tests.yml (2)

49-54: Inline one-liner Flask app is brittle & hard to read

Packing the entire Flask micro-app into a single echo line with multiple semicolons is error-prone and painful to maintain.
A minimal refactor dramatically improves clarity while retaining the same behaviour:

-        echo "from flask import Flask; from platzky_b4uleave.entrypoint import process; app = Flask(__name__); app.route('/')(process)" > temp_app.py
+        cat > temp_app.py <<'PY'
+from flask import Flask
+from platzky_b4uleave.entrypoint import process
+
+app = Flask(__name__)
+app.route('/')(process)
+PY

No functional change, just readability and lower risk of quoting bugs.
(Optional but strongly recommended.)


42-46: Consider caching & pinning Cypress installation

npm install cypress re-downloads Cypress on every run, which slows the workflow.
Using the official cypress-io/github-action (or at minimum enabling Node-module caching with actions/setup-node’s cache: 'npm') will cut several minutes off CI times and improve reliability.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between eaa3f2d and 910140a.

📒 Files selected for processing (2)
  • .github/workflows/tests.yml (1 hunks)
  • tests/unit_tests/test_b4uleave.py (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/unit_tests/test_b4uleave.py

Comment thread .github/workflows/tests.yml Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
.github/workflows/tests.yml (1)

56-56: Remove trailing whitespace to keep YAML lint-clean

Line 56 has trailing spaces flagged by YAMLlint. Deleting them avoids CI noise.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c061f9e and 4a3c908.

📒 Files selected for processing (1)
  • .github/workflows/tests.yml (1 hunks)
🧰 Additional context used
🪛 YAMLlint (1.37.1)
.github/workflows/tests.yml

[error] 56-56: trailing spaces

(trailing-spaces)

🔇 Additional comments (3)
.github/workflows/tests.yml (3)

61-63: Confirm Cypress spec glob is correct relative to working directory

working-directory is already tests/e2e_tests, so "cypress/e2e/**/*" resolves to tests/e2e_tests/cypress/e2e/**/*. Verify this matches the repo layout; otherwise the run will report “No tests found”.


47-50: Hosts file addition looks good

Binding the Flask server to goodmap.localhost and pre-populating /etc/hosts is clear and portable.


53-58: PID management still inconsistent—Flask process will not be terminated

You write the PID to flask.pid, but never export FLASK_PID. Consequently, the “Stop Flask server” step sends a signal to an empty variable, leaving the background Flask process running and subsequent jobs flaky.

-        echo $! > flask.pid
+        echo $! > flask.pid
+        export FLASK_PID=$!

or simply change the kill step:

-      run: kill $FLASK_PID || true
+      run: kill $(cat flask.pid) || true

Likely an incorrect or invalid review comment.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
.github/workflows/tests.yml (1)

30-30: Trailing whitespace flagged by YAML-lint

Lines 30 and 52 contain superfluous spaces, which YAML-lint reports as errors. Remove the extra spaces to keep the workflow lint-clean.

Also applies to: 52-52

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4a3c908 and 32ab65d.

📒 Files selected for processing (1)
  • .github/workflows/tests.yml (2 hunks)
🧰 Additional context used
🪛 YAMLlint (1.37.1)
.github/workflows/tests.yml

[error] 30-30: trailing spaces

(trailing-spaces)


[error] 52-52: trailing spaces

(trailing-spaces)


[error] 61-61: syntax error: could not find expected ':'

(syntax)

🪛 actionlint (1.7.7)
.github/workflows/tests.yml

60-60: could not parse as YAML: yaml: line 60: could not find expected ':'

(syntax-check)

🔇 Additional comments (1)
.github/workflows/tests.yml (1)

66-68: Stop Flask server step is mis-indented and refers to an undefined PID

  1. The - name: line is at the root level, not inside the steps: list, so even after fixing the conflict markers this will still break YAML.
  2. $FLASK_PID is never exported now that the Flask server start step is commented out, so kill $FLASK_PID will do nothing.

Either:
• Drop this step entirely, or
• Re-enable the server start step and export FLASK_PID, then indent this block with four spaces so it’s a sibling of the other steps.

Example removal:

-# Stop the Flask server using the saved process ID
-- name: Stop Flask server
-  run: kill $FLASK_PID || true

Comment thread .github/workflows/tests.yml Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 32ab65d and 4991288.

📒 Files selected for processing (1)
  • .github/workflows/tests.yml (2 hunks)
🧰 Additional context used
🪛 YAMLlint (1.37.1)
.github/workflows/tests.yml

[error] 30-30: trailing spaces

(trailing-spaces)

🔇 Additional comments (1)
.github/workflows/tests.yml (1)

30-30: Remove trailing whitespace to satisfy linters

Line 30 has stray spaces flagged by YAML-lint. Delete them to keep the workflow lint-clean.

[ suggest_nitpick ]

Comment thread .github/workflows/tests.yml Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (5)
tests/e2e_tests/cypress.config.js (1)

5-5: Option: prefer 127.0.0.1 to avoid IPv6 localhost pitfalls on runners

Some runners resolve localhost to ::1 which can cause transient connect issues. Consider pinning IPv4.

Apply this minimal change:

-    baseUrl: 'http://localhost:5000/',
+    baseUrl: 'http://127.0.0.1:5000/',
tests/e2e_tests/e2e_test_config.yml (3)

8-8: Remove stray TODO comment from committed test config

Keep committed configs free of TODOs; track this in an issue if needed.

Apply:

-#TODO this should not be necessary argument

20-21: Normalize YAML booleans to lowercase (style/lint consistency)

Lowercase booleans are commonly enforced by linters.

Apply:

-  USE_LAZY_LOADING: True
-  SHOW_ACCESSIBILITY_TABLE: True
+  USE_LAZY_LOADING: true
+  SHOW_ACCESSIBILITY_TABLE: true

21-21: Add trailing newline at EOF

YAMLlint flagged “no new line character at the end of file”. Configure your editor to add a newline on save.

tests/e2e_tests/e2e_app.py (1)

5-7: Add return type and import Flask for clarity and tooling

Helps IDEs and type checkers; no runtime impact.

Apply:

-from flask import render_template_string
+from flask import Flask, render_template_string
@@
-def create_app(config_path: str):
+def create_app(config_path: str) -> Flask:
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 4991288 and 2f79ff4.

📒 Files selected for processing (5)
  • .github/workflows/tests.yml (1 hunks)
  • tests/e2e_tests/cypress.config.js (1 hunks)
  • tests/e2e_tests/e2e_app.py (1 hunks)
  • tests/e2e_tests/e2e_test_config.yml (1 hunks)
  • tests/e2e_tests/e2e_test_data.json (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • tests/e2e_tests/e2e_test_data.json
🧰 Additional context used
🧬 Code graph analysis (1)
tests/e2e_tests/e2e_app.py (1)
tests/unit_tests/test_b4uleave.py (1)
  • test_that_plugin_loads_b4uleave (5-53)
🪛 YAMLlint (1.37.1)
tests/e2e_tests/e2e_test_config.yml

[error] 21-21: no new line character at the end of file

(new-line-at-end-of-file)

🔇 Additional comments (3)
tests/e2e_tests/cypress.config.js (1)

5-5: LGTM: baseUrl aligns with the workflow

Matches Flask binding to localhost:5000. Nothing else to change here.

tests/e2e_tests/e2e_test_config.yml (1)

4-7: Verify JSON file DB driver registration

  • Data file tests/e2e_tests/e2e_test_data.json exists and contains the "name": "b4uleave" entry.
  • Confirm the app factory supports DB.TYPE: json_file and correctly loads its data from the specified DB.PATH.
tests/e2e_tests/e2e_app.py (1)

9-29: LGTM: minimal HTML shell suitable for plugin injection

Route wiring and template are fine for the e2e scenario.

Comment on lines +48 to +50
poetry run flask --app "tests.e2e_tests.e2e_app:create_app(config_path='tests/e2e_tests/e2e_test_config.yml')" run --debug --host=localhost &
sleep 6
cd tests/e2e_tests && npx cypress run --spec "cypress/e2e/**/*"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Harden e2e step: avoid reloader, wait for readiness, and ensure clean teardown

Current approach uses --debug (spawns a reloader) and a fixed sleep which can flake. Start a single process, wait until it’s responsive, and always kill it on exit.

Apply:

-        poetry run flask --app "tests.e2e_tests.e2e_app:create_app(config_path='tests/e2e_tests/e2e_test_config.yml')" run --debug --host=localhost &
-        sleep 6
-        cd tests/e2e_tests && npx cypress run --spec "cypress/e2e/**/*"
+        set -euo pipefail
+        poetry run flask --app "tests.e2e_tests.e2e_app:create_app(config_path='tests/e2e_tests/e2e_test_config.yml')" run --host=127.0.0.1 --port=5000 --no-reload > flask.log 2>&1 &
+        SERVER_PID=$!
+        trap 'kill "$SERVER_PID" || true' EXIT
+        # Wait up to 30s for server readiness
+        for i in {1..30}; do
+          curl -fsS http://127.0.0.1:5000/ >/dev/null && break
+          sleep 1
+        done
+        cd tests/e2e_tests
+        npx cypress run --spec "cypress/e2e/**/*"

Optional: upload flask.log on failure to aid debugging.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
poetry run flask --app "tests.e2e_tests.e2e_app:create_app(config_path='tests/e2e_tests/e2e_test_config.yml')" run --debug --host=localhost &
sleep 6
cd tests/e2e_tests && npx cypress run --spec "cypress/e2e/**/*"
set -euo pipefail
poetry run flask --app "tests.e2e_tests.e2e_app:create_app(config_path='tests/e2e_tests/e2e_test_config.yml')" \
run --host=127.0.0.1 --port=5000 --no-reload > flask.log 2>&1 &
SERVER_PID=$!
trap 'kill "$SERVER_PID" || true' EXIT
# Wait up to 30s for server readiness
for i in {1..30}; do
curl -fsS http://127.0.0.1:5000/ >/dev/null && break
sleep 1
done
cd tests/e2e_tests
npx cypress run --spec "cypress/e2e/**/*"
🤖 Prompt for AI Agents
.github/workflows/tests.yml lines 48-50: the e2e job currently launches Flask
with --debug (which spawns a reloader) and uses a fixed sleep, causing flakiness
and orphaned processes; change to start a single, non-reloading Flask process
(use the CLI flag to disable the reloader), run it in background capturing its
PID, install a trap/cleanup to always kill that PID on EXIT, replace the fixed
sleep with a readiness probe loop (poll the app URL with a short timeout and
bounded retries until a 200/healthy response or fail), and on failure upload
flask.log for debugging; ensure the readiness loop times out and exits non-zero
so Cypress doesn’t run against an unready server.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants