Skip to content

[fix] Fix duplicate template entries in Device admin#1303

Merged
nemesifier merged 4 commits intomasterfrom
fix-relevant-templates
Mar 27, 2026
Merged

[fix] Fix duplicate template entries in Device admin#1303
nemesifier merged 4 commits intomasterfrom
fix-relevant-templates

Conversation

@pandafy
Copy link
Copy Markdown
Member

@pandafy pandafy commented Mar 20, 2026

Checklist

  • I have read the OpenWISP Contributing Guidelines.
  • I have manually tested the changes proposed in this pull request.
  • I have written new test cases for new code and/or updated existing tests for changes to existing code.
  • I have updated the documentation.

Description of Changes

Bug:
The JS logic in relevant_templates.js assumed that the last ul.sortedm2m-items element belonged to the empty inline form used by Django admin formsets. This assumption breaks when the user does not have permission to add Config objects: in that case the ConfigInlineAdmin does not render the empty form.

As a result, both selectors ended up referencing the same list and the script appended template elements twice to the same sortedm2m list, causing duplicate entries and issues when saving the form.

Fix:
Select the empty form container explicitly using #config-empty ul.sortedm2m-items instead of relying on the last occurrence of ul.sortedm2m-items. This ensures the logic works correctly regardless of whether the empty inline form is rendered.

@pandafy pandafy self-assigned this Mar 20, 2026
@pandafy pandafy moved this to In progress in OpenWISP Contributor's Board Mar 20, 2026
@pandafy pandafy moved this from In progress to Needs review in OpenWISP Contributor's Board Mar 20, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 20, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

showRelevantTemplates() now uses the specific container selector "#config-empty ul.sortedm2m-items" for inserting per-template prefix

  • elements when !isDeviceGroup(), replacing the previous $("ul.sortedm2m-items:last") selection. The Selenium test helper _verify_templates_visibility() scopes template checkbox lookups to inputs under the sortedm2m widget (XPath targeting //ul[contains(@Class,"sortedm2m-items")]//input[@value="..."]). A new UI test TestDeviceAdmin.test_relevant_templates_duplicates creates two shared templates and verifies they render as two li.sortedm2m-item entries with expected checkbox ids, values, and data-required="false", then saves. A geo test builds the admin change URL dynamically from the model's app_label and model_name.

    Estimated code review effort

    🎯 4 (Complex) | ⏱️ ~45 minutes


  • Important

    Pre-merge checks failed

    Please resolve all errors before merging. Addressing warnings is optional.

    ❌ Failed checks (1 inconclusive)

    Check name Status Explanation Resolution
    Bug Fixes ❓ Inconclusive Unable to verify - shell commands cannot be executed in this environment. Please execute the verification commands directly in your development environment and review the files specified.
    ✅ Passed checks (2 passed)
    Check name Status Explanation
    Title check ✅ Passed The title includes the required [fix] prefix and clearly describes the main change: fixing duplicate template entries in the Device admin interface.
    Description check ✅ Passed The description covers all required sections including checklist completion, clear explanation of the bug and fix, though documentation update is unchecked.
    ✨ Finishing Touches
    🧪 Generate unit tests (beta)
    • Create PR with unit tests
    • Commit unit tests in branch fix-relevant-templates

    Comment @coderabbitai help to get the list of available commands and usage tips.

    @pandafy
    Copy link
    Copy Markdown
    Member Author

    pandafy commented Mar 20, 2026

    Possible changelog entry

    Fixed an issue where relevant configuration templates could appear
    duplicated in the Device admin when the user lacked permission to add
    Config objects.

    Copy link
    Copy Markdown
    Contributor

    @coderabbitai coderabbitai bot left a comment

    Choose a reason for hiding this comment

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

    Actionable comments posted: 1

    🤖 Prompt for all review comments with AI agents
    Verify each finding against the current code and only fix it if needed.
    
    Inline comments:
    In `@openwisp_controller/config/tests/test_selenium.py`:
    - Around line 470-483: The test uses brittle string matching on
    self.web_driver.page_source to assert checkbox HTML; replace this with DOM-based
    assertions using Selenium APIs: for each template_id/idx in the loop, locate the
    checkbox element (e.g., via find_element using a CSS selector combining
    input[type="checkbox"] and value="{template_id}" or by id
    "id_config-templates_{idx}") and then assert the relevant attributes (type,
    value, id, class and data-required) via element.get_attribute(...) or
    element.get_property(...); update imports to include
    selenium.webdriver.common.by.By or WebDriverWait as needed and change the
    assertions in the test method that currently references page_source to use these
    DOM attribute checks on the found element.
    
    🪄 Autofix (Beta)

    Fix all unresolved CodeRabbit comments on this PR:

    • Push a commit to this branch (recommended)
    • Create a new PR with the fixes

    ℹ️ Review info
    ⚙️ Run configuration

    Configuration used: Organization UI

    Review profile: ASSERTIVE

    Plan: Pro

    Run ID: e69f4e33-19ed-44f9-94d0-99b9f27c73f8

    📥 Commits

    Reviewing files that changed from the base of the PR and between 45b24b6 and 89bdba1.

    📒 Files selected for processing (2)
    • openwisp_controller/config/static/config/js/relevant_templates.js
    • openwisp_controller/config/tests/test_selenium.py
    📜 Review details
    ⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (14)
    • GitHub Check: Analyze (actions)
    • GitHub Check: Analyze (javascript-typescript)
    • GitHub Check: Analyze (python)
    • GitHub Check: Python==3.13 | django~=5.1.0
    • GitHub Check: Python==3.10 | django~=5.2.0
    • GitHub Check: Python==3.12 | django~=5.2.0
    • GitHub Check: Python==3.13 | django~=5.2.0
    • GitHub Check: Python==3.11 | django~=5.2.0
    • GitHub Check: Python==3.12 | django~=5.1.0
    • GitHub Check: Python==3.11 | django~=5.1.0
    • GitHub Check: Python==3.10 | django~=5.1.0
    • GitHub Check: Python==3.11 | django~=4.2.0
    • GitHub Check: Python==3.12 | django~=4.2.0
    • GitHub Check: Python==3.10 | django~=4.2.0
    🧰 Additional context used
    📓 Path-based instructions (4)
    **/*.{js,ts,tsx,jsx,py,java,go,cs,rb,php,c,cpp,h,hpp}

    📄 CodeRabbit inference engine (Custom checks)

    **/*.{js,ts,tsx,jsx,py,java,go,cs,rb,php,c,cpp,h,hpp}: Flag potential security vulnerabilities in code
    Avoid unnecessary comments or docstrings for code that is already clear
    Code formatting is compact and readable. Do not add excessive blank lines, especially inside function or method bodies
    Flag unused or redundant code
    Ensure variables, functions, classes, and files have descriptive and consistent names
    New code must handle errors properly: log errors that cannot be resolved by the user with error level, log unusual conditions with warning level, log important background actions with info level, and provide user-facing messages for errors that the user can solve autonomously

    Files:

    • openwisp_controller/config/static/config/js/relevant_templates.js
    • openwisp_controller/config/tests/test_selenium.py
    **/*.{js,ts,tsx,jsx,py,java,go,cs,rb,php,c,cpp,h,hpp,sql}

    📄 CodeRabbit inference engine (Custom checks)

    Flag obvious performance regressions, such as heavy loops, repeated I/O, or unoptimized queries

    Files:

    • openwisp_controller/config/static/config/js/relevant_templates.js
    • openwisp_controller/config/tests/test_selenium.py
    **/*.{js,ts,tsx,jsx,py,java,go,cs,rb,php,c,cpp,h,hpp,sh,bash,sql}

    📄 CodeRabbit inference engine (Custom checks)

    Cryptic or non-obvious code (regex, complex bash commands, or hard-to-read code) must include a concise comment explaining why it is needed and why the complexity is acceptable

    Files:

    • openwisp_controller/config/static/config/js/relevant_templates.js
    • openwisp_controller/config/tests/test_selenium.py
    **/*.{py,html}

    📄 CodeRabbit inference engine (Custom checks)

    For Django pull requests, ensure all user-facing strings are marked as translatable using the Django i18n framework

    Files:

    • openwisp_controller/config/tests/test_selenium.py
    🧠 Learnings (4)
    📓 Common learnings
    Learnt from: CR
    Repo: openwisp/openwisp-controller PR: 0
    File: coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt:0-0
    Timestamp: 2026-03-14T19:34:33.773Z
    Learning: Applies to **/*{.test,.spec,_test,test_}.{js,ts,tsx,jsx,py,java,go,cs,rb} : Tests must be updated to cover non-trivial changes and ensure proper validation of modified behavior
    
    Learnt from: CR
    Repo: openwisp/openwisp-controller PR: 0
    File: coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt:0-0
    Timestamp: 2026-03-14T19:34:33.773Z
    Learning: Applies to **/*{.test,.spec,_test,test_}.{js,ts,tsx,jsx,py,java,go,cs,rb} **/*.{e2e,browser,selenium}.{js,ts,tsx,jsx} : For feature requests, tests are added and coverage does not decrease significantly. If the feature impacts the UI, Selenium browser tests are preferred
    
    📚 Learning: 2026-01-15T15:05:49.557Z
    Learnt from: DragnEmperor
    Repo: openwisp/openwisp-controller PR: 1175
    File: openwisp_controller/config/management/commands/clear_last_ip.py:38-42
    Timestamp: 2026-01-15T15:05:49.557Z
    Learning: In Django projects, when using select_related() to traverse relations (for example, select_related("organization__config_settings")), the traversed relation must not be deferred. If you also use .only() in the same query, include the relation name or FK field (e.g., "organization" or "organization_id") in the .only() list to avoid the error "Field X cannot be both deferred and traversed using select_related at the same time." Apply this guideline to Django code in openwisp_controller/config/management/commands/clear_last_ip.py and similar modules by ensuring any select_related with an accompanying only() includes the related field names to prevent deferred/traversed conflicts.
    

    Applied to files:

    • openwisp_controller/config/tests/test_selenium.py
    📚 Learning: 2026-02-17T19:13:10.088Z
    Learnt from: nemesifier
    Repo: openwisp/openwisp-controller PR: 1175
    File: openwisp_controller/config/whois/commands.py:0-0
    Timestamp: 2026-02-17T19:13:10.088Z
    Learning: In reviews for the openwisp/openwisp-controller repository, do not propose changes based on Ruff warnings. The project does not use Ruff as its linter; ignore Ruff-related suggestions and follow the repository’s established linting and configuration rules. This guidance applies to all Python files under the openwisp_controller directory.
    

    Applied to files:

    • openwisp_controller/config/tests/test_selenium.py
    📚 Learning: 2026-01-15T15:07:17.354Z
    Learnt from: DragnEmperor
    Repo: openwisp/openwisp-controller PR: 1175
    File: openwisp_controller/geo/estimated_location/tests/tests.py:172-175
    Timestamp: 2026-01-15T15:07:17.354Z
    Learning: In this repository, flake8 enforces E501 (line too long) via setup.cfg (max-line-length = 88) while ruff ignores E501 via ruff.toml. Therefore, use '# noqa: E501' on lines that intentionally exceed 88 characters to satisfy flake8 without affecting ruff checks. This applies to Python files across the project (any .py) and is relevant for tests as well. Use sparingly and only where breaking lines is not feasible without hurting readability or functionality.
    

    Applied to files:

    • openwisp_controller/config/tests/test_selenium.py
    🧬 Code graph analysis (1)
    openwisp_controller/config/tests/test_selenium.py (2)
    openwisp_controller/config/tests/utils.py (3)
    • _create_template (77-87)
    • _create_config (60-73)
    • _create_config (396-401)
    openwisp_controller/geo/tests/test_selenium.py (1)
    • wait_for_presence (43-44)
    🔇 Additional comments (2)
    openwisp_controller/config/static/config/js/relevant_templates.js (1)

    141-141: Selector fix correctly removes duplicate append risk.

    Targeting #config-empty ul.sortedm2m-items makes the insertion point deterministic and prevents the double-append behavior when the empty inline is not rendered.

    openwisp_controller/config/tests/test_selenium.py (1)

    49-59: Scoped template visibility locators are a solid improvement.

    Using the ul.sortedm2m-items-scoped XPath makes these checks less error-prone than broad page-level value matching.

    @github-project-automation github-project-automation bot moved this from Needs review to In progress in OpenWISP Contributor's Board Mar 20, 2026
    @pandafy pandafy force-pushed the fix-relevant-templates branch from 89bdba1 to 7ea2118 Compare March 20, 2026 10:37
    @openwisp-companion
    Copy link
    Copy Markdown

    Flake8 E501 Line Too Long Failures

    Hello @pandafy,
    (Analysis for commit 89bdba1)

    The CI failed because several lines in the openwisp_controller/config/tests/test_selenium.py file exceed the maximum line length of 88 characters.

    Fix:
    Please manually shorten the following lines:

    • openwisp_controller/config/tests/test_selenium.py:463:89
    • openwisp_controller/config/tests/test_selenium.py:468:89
    • openwisp_controller/config/tests/test_selenium.py:475:89
    • openwisp_controller/config/tests/test_selenium.py:481:89

    Copy link
    Copy Markdown
    Contributor

    @coderabbitai coderabbitai bot left a comment

    Choose a reason for hiding this comment

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

    ♻️ Duplicate comments (1)
    openwisp_controller/config/tests/test_selenium.py (1)

    468-487: ⚠️ Potential issue | 🟠 Major

    Replace brittle page_source HTML matching with DOM-level assertions.

    The current check depends on serialized HTML text shape (including attribute order), which is flaky across browsers/drivers and can fail even when behavior is correct.

    Proposed fix
    -        with self.subTest(
    -            "Verify checkbox HTML elements are present in page source"
    -            " with correct attributes"
    -        ):
    -            page_source = self.web_driver.page_source
    -            # Verify HTML element strings for each template
    -            for idx, template_id in enumerate([template1.id, template2.id], start=0):
    -                html_element = (
    -                    f'<input type="checkbox" value="{template_id}" '
    -                    f'id="id_config-templates_{idx}" class="sortedm2m"'
    -                    ' data-required="false"'
    -                )
    -                self.assertIn(
    -                    html_element,
    -                    page_source,
    -                    (
    -                        f"Expected checkbox HTML for template {template_id} not found"
    -                        " in page source"
    -                    ),
    -                )
    +        with self.subTest("Verify checkbox inputs have expected attributes"):
    +            for idx, template in enumerate([template1, template2]):
    +                checkbox = self.find_element(
    +                    by=By.ID, value=f"id_config-templates_{idx}"
    +                )
    +                self.assertEqual(checkbox.get_attribute("value"), str(template.id))
    +                self.assertEqual(checkbox.get_attribute("data-required"), "false")
    #!/bin/bash
    # Verify whether page_source-based HTML assertions still exist in selenium tests.
    rg -n -C3 'page_source|html_element|assertIn\(' --type=py

    Based on learnings: Tests must be updated to cover non-trivial changes and ensure proper validation of modified behavior.

    🤖 Prompt for AI Agents
    Verify each finding against the current code and only fix it if needed.
    
    In `@openwisp_controller/config/tests/test_selenium.py` around lines 468 - 487,
    Replace the brittle page_source string match in the subTest block: instead of
    building html_element and using page_source / self.assertIn, query the DOM via
    the Selenium WebDriver (self.web_driver) for checkbox inputs corresponding to
    each template (use value==template_id and id==f"id_config-templates_{idx}" or
    class/specific attributes) and assert presence/count using find_element(s) or
    appropriate By selectors; remove reliance on the page_source variable and the
    html_element string and update the assertions that currently call self.assertIn
    to check the found element(s) exist and have the expected attributes (e.g.,
    type="checkbox", class contains "sortedm2m", data-required="false") for
    template1.id and template2.id.
    
    🤖 Prompt for all review comments with AI agents
    Verify each finding against the current code and only fix it if needed.
    
    Duplicate comments:
    In `@openwisp_controller/config/tests/test_selenium.py`:
    - Around line 468-487: Replace the brittle page_source string match in the
    subTest block: instead of building html_element and using page_source /
    self.assertIn, query the DOM via the Selenium WebDriver (self.web_driver) for
    checkbox inputs corresponding to each template (use value==template_id and
    id==f"id_config-templates_{idx}" or class/specific attributes) and assert
    presence/count using find_element(s) or appropriate By selectors; remove
    reliance on the page_source variable and the html_element string and update the
    assertions that currently call self.assertIn to check the found element(s) exist
    and have the expected attributes (e.g., type="checkbox", class contains
    "sortedm2m", data-required="false") for template1.id and template2.id.
    

    ℹ️ Review info
    ⚙️ Run configuration

    Configuration used: Organization UI

    Review profile: ASSERTIVE

    Plan: Pro

    Run ID: 9ae9485e-3d78-4084-9dae-d09dc6c14147

    📥 Commits

    Reviewing files that changed from the base of the PR and between 89bdba1 and 7ea2118.

    📒 Files selected for processing (2)
    • openwisp_controller/config/static/config/js/relevant_templates.js
    • openwisp_controller/config/tests/test_selenium.py
    📜 Review details
    ⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
    • GitHub Check: Python==3.10 | django~=5.2.0
    • GitHub Check: Python==3.13 | django~=5.2.0
    • GitHub Check: Python==3.12 | django~=5.1.0
    • GitHub Check: Python==3.10 | django~=4.2.0
    • GitHub Check: Python==3.11 | django~=4.2.0
    • GitHub Check: Python==3.12 | django~=5.2.0
    • GitHub Check: Python==3.10 | django~=5.1.0
    • GitHub Check: Python==3.11 | django~=5.1.0
    • GitHub Check: Python==3.13 | django~=5.1.0
    • GitHub Check: Python==3.12 | django~=4.2.0
    • GitHub Check: Python==3.11 | django~=5.2.0
    🧰 Additional context used
    📓 Path-based instructions (4)
    **/*.{js,ts,tsx,jsx,py,java,go,cs,rb,php,c,cpp,h,hpp}

    📄 CodeRabbit inference engine (Custom checks)

    **/*.{js,ts,tsx,jsx,py,java,go,cs,rb,php,c,cpp,h,hpp}: Flag potential security vulnerabilities in code
    Avoid unnecessary comments or docstrings for code that is already clear
    Code formatting is compact and readable. Do not add excessive blank lines, especially inside function or method bodies
    Flag unused or redundant code
    Ensure variables, functions, classes, and files have descriptive and consistent names
    New code must handle errors properly: log errors that cannot be resolved by the user with error level, log unusual conditions with warning level, log important background actions with info level, and provide user-facing messages for errors that the user can solve autonomously

    Files:

    • openwisp_controller/config/static/config/js/relevant_templates.js
    • openwisp_controller/config/tests/test_selenium.py
    **/*.{js,ts,tsx,jsx,py,java,go,cs,rb,php,c,cpp,h,hpp,sql}

    📄 CodeRabbit inference engine (Custom checks)

    Flag obvious performance regressions, such as heavy loops, repeated I/O, or unoptimized queries

    Files:

    • openwisp_controller/config/static/config/js/relevant_templates.js
    • openwisp_controller/config/tests/test_selenium.py
    **/*.{js,ts,tsx,jsx,py,java,go,cs,rb,php,c,cpp,h,hpp,sh,bash,sql}

    📄 CodeRabbit inference engine (Custom checks)

    Cryptic or non-obvious code (regex, complex bash commands, or hard-to-read code) must include a concise comment explaining why it is needed and why the complexity is acceptable

    Files:

    • openwisp_controller/config/static/config/js/relevant_templates.js
    • openwisp_controller/config/tests/test_selenium.py
    **/*.{py,html}

    📄 CodeRabbit inference engine (Custom checks)

    For Django pull requests, ensure all user-facing strings are marked as translatable using the Django i18n framework

    Files:

    • openwisp_controller/config/tests/test_selenium.py
    🧠 Learnings (5)
    📚 Learning: 2026-03-14T19:34:33.773Z
    Learnt from: CR
    Repo: openwisp/openwisp-controller PR: 0
    File: coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt:0-0
    Timestamp: 2026-03-14T19:34:33.773Z
    Learning: Applies to **/*.{e2e,browser,selenium}.{js,ts,tsx,jsx} : If a bug affects the user interface, include a Selenium browser test; if missing, raise a warning
    

    Applied to files:

    • openwisp_controller/config/tests/test_selenium.py
    📚 Learning: 2026-03-14T19:34:33.773Z
    Learnt from: CR
    Repo: openwisp/openwisp-controller PR: 0
    File: coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt:0-0
    Timestamp: 2026-03-14T19:34:33.773Z
    Learning: Applies to **/*{.test,.spec,_test,test_}.{js,ts,tsx,jsx,py,java,go,cs,rb} : Tests must be updated to cover non-trivial changes and ensure proper validation of modified behavior
    

    Applied to files:

    • openwisp_controller/config/tests/test_selenium.py
    📚 Learning: 2026-01-15T15:05:49.557Z
    Learnt from: DragnEmperor
    Repo: openwisp/openwisp-controller PR: 1175
    File: openwisp_controller/config/management/commands/clear_last_ip.py:38-42
    Timestamp: 2026-01-15T15:05:49.557Z
    Learning: In Django projects, when using select_related() to traverse relations (for example, select_related("organization__config_settings")), the traversed relation must not be deferred. If you also use .only() in the same query, include the relation name or FK field (e.g., "organization" or "organization_id") in the .only() list to avoid the error "Field X cannot be both deferred and traversed using select_related at the same time." Apply this guideline to Django code in openwisp_controller/config/management/commands/clear_last_ip.py and similar modules by ensuring any select_related with an accompanying only() includes the related field names to prevent deferred/traversed conflicts.
    

    Applied to files:

    • openwisp_controller/config/tests/test_selenium.py
    📚 Learning: 2026-02-17T19:13:10.088Z
    Learnt from: nemesifier
    Repo: openwisp/openwisp-controller PR: 1175
    File: openwisp_controller/config/whois/commands.py:0-0
    Timestamp: 2026-02-17T19:13:10.088Z
    Learning: In reviews for the openwisp/openwisp-controller repository, do not propose changes based on Ruff warnings. The project does not use Ruff as its linter; ignore Ruff-related suggestions and follow the repository’s established linting and configuration rules. This guidance applies to all Python files under the openwisp_controller directory.
    

    Applied to files:

    • openwisp_controller/config/tests/test_selenium.py
    📚 Learning: 2026-01-15T15:07:17.354Z
    Learnt from: DragnEmperor
    Repo: openwisp/openwisp-controller PR: 1175
    File: openwisp_controller/geo/estimated_location/tests/tests.py:172-175
    Timestamp: 2026-01-15T15:07:17.354Z
    Learning: In this repository, flake8 enforces E501 (line too long) via setup.cfg (max-line-length = 88) while ruff ignores E501 via ruff.toml. Therefore, use '# noqa: E501' on lines that intentionally exceed 88 characters to satisfy flake8 without affecting ruff checks. This applies to Python files across the project (any .py) and is relevant for tests as well. Use sparingly and only where breaking lines is not feasible without hurting readability or functionality.
    

    Applied to files:

    • openwisp_controller/config/tests/test_selenium.py
    🧬 Code graph analysis (1)
    openwisp_controller/config/tests/test_selenium.py (1)
    openwisp_controller/config/tests/utils.py (3)
    • _create_template (77-87)
    • _create_config (60-73)
    • _create_config (396-401)
    🔇 Additional comments (1)
    openwisp_controller/config/static/config/js/relevant_templates.js (1)

    140-142: Selector fix correctly removes the duplicate-template root cause.

    Switching to #config-empty ul.sortedm2m-items removes DOM-order dependency and safely avoids duplicate append behavior when the empty inline is not rendered.

    @coveralls
    Copy link
    Copy Markdown

    coveralls commented Mar 20, 2026

    Coverage Status

    coverage: 98.66% (+0.01%) from 98.646%
    when pulling 4c9e834 on fix-relevant-templates
    into af0d99b on master.

    @kilo-code-bot
    Copy link
    Copy Markdown

    kilo-code-bot bot commented Mar 23, 2026

    Kilo Code Review could not run — your account is out of credits.

    Add credits at app.kilo.ai to enable reviews on this change.

    Copy link
    Copy Markdown
    Contributor

    @coderabbitai coderabbitai bot left a comment

    Choose a reason for hiding this comment

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

    Actionable comments posted: 1

    🤖 Prompt for all review comments with AI agents
    Verify each finding against the current code and only fix it if needed.
    
    Inline comments:
    In `@openwisp_controller/config/tests/test_selenium.py`:
    - Around line 444-446: The test opens the admin device change URL with a
    hardcoded "admin:config_device_change" but should use the class attribute for
    app label consistency; update the call in the test method (the one that invokes
    self.open(...)) to build the URL with
    f"admin:{self.config_app_label}_device_change" (using reverse with
    args=[device.id] and the same "#config-group" fragment) so it matches other
    tests that reference self.config_app_label.
    
    🪄 Autofix (Beta)

    Fix all unresolved CodeRabbit comments on this PR:

    • Push a commit to this branch (recommended)
    • Create a new PR with the fixes

    ℹ️ Review info
    ⚙️ Run configuration

    Configuration used: Organization UI

    Review profile: ASSERTIVE

    Plan: Pro

    Run ID: 3d82e577-a83c-478d-b910-232843546d87

    📥 Commits

    Reviewing files that changed from the base of the PR and between 7ea2118 and 63ce379.

    📒 Files selected for processing (1)
    • openwisp_controller/config/tests/test_selenium.py
    📜 Review details
    ⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
    • GitHub Check: Python==3.13 | django~=5.2.0
    • GitHub Check: Python==3.12 | django~=5.1.0
    • GitHub Check: Python==3.13 | django~=5.1.0
    • GitHub Check: Python==3.11 | django~=4.2.0
    • GitHub Check: Python==3.11 | django~=5.1.0
    • GitHub Check: Python==3.10 | django~=5.2.0
    • GitHub Check: Python==3.12 | django~=5.2.0
    • GitHub Check: Python==3.10 | django~=4.2.0
    • GitHub Check: Python==3.12 | django~=4.2.0
    • GitHub Check: Python==3.11 | django~=5.2.0
    • GitHub Check: Python==3.10 | django~=5.1.0
    🧰 Additional context used
    📓 Path-based instructions (4)
    **/*.{js,ts,tsx,jsx,py,java,go,cs,rb,php,c,cpp,h,hpp}

    📄 CodeRabbit inference engine (Custom checks)

    **/*.{js,ts,tsx,jsx,py,java,go,cs,rb,php,c,cpp,h,hpp}: Flag potential security vulnerabilities in code
    Avoid unnecessary comments or docstrings for code that is already clear
    Code formatting is compact and readable. Do not add excessive blank lines, especially inside function or method bodies
    Flag unused or redundant code
    Ensure variables, functions, classes, and files have descriptive and consistent names
    New code must handle errors properly: log errors that cannot be resolved by the user with error level, log unusual conditions with warning level, log important background actions with info level, and provide user-facing messages for errors that the user can solve autonomously

    Files:

    • openwisp_controller/config/tests/test_selenium.py
    **/*.{js,ts,tsx,jsx,py,java,go,cs,rb,php,c,cpp,h,hpp,sql}

    📄 CodeRabbit inference engine (Custom checks)

    Flag obvious performance regressions, such as heavy loops, repeated I/O, or unoptimized queries

    Files:

    • openwisp_controller/config/tests/test_selenium.py
    **/*.{js,ts,tsx,jsx,py,java,go,cs,rb,php,c,cpp,h,hpp,sh,bash,sql}

    📄 CodeRabbit inference engine (Custom checks)

    Cryptic or non-obvious code (regex, complex bash commands, or hard-to-read code) must include a concise comment explaining why it is needed and why the complexity is acceptable

    Files:

    • openwisp_controller/config/tests/test_selenium.py
    **/*.{py,html}

    📄 CodeRabbit inference engine (Custom checks)

    For Django pull requests, ensure all user-facing strings are marked as translatable using the Django i18n framework

    Files:

    • openwisp_controller/config/tests/test_selenium.py
    🧠 Learnings (5)
    📚 Learning: 2026-03-14T19:34:33.773Z
    Learnt from: CR
    Repo: openwisp/openwisp-controller PR: 0
    File: coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt:0-0
    Timestamp: 2026-03-14T19:34:33.773Z
    Learning: Applies to **/*.{e2e,browser,selenium}.{js,ts,tsx,jsx} : If a bug affects the user interface, include a Selenium browser test; if missing, raise a warning
    

    Applied to files:

    • openwisp_controller/config/tests/test_selenium.py
    📚 Learning: 2026-03-14T19:34:33.773Z
    Learnt from: CR
    Repo: openwisp/openwisp-controller PR: 0
    File: coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt:0-0
    Timestamp: 2026-03-14T19:34:33.773Z
    Learning: Applies to **/*{.test,.spec,_test,test_}.{js,ts,tsx,jsx,py,java,go,cs,rb} : Tests must be updated to cover non-trivial changes and ensure proper validation of modified behavior
    

    Applied to files:

    • openwisp_controller/config/tests/test_selenium.py
    📚 Learning: 2026-01-15T15:05:49.557Z
    Learnt from: DragnEmperor
    Repo: openwisp/openwisp-controller PR: 1175
    File: openwisp_controller/config/management/commands/clear_last_ip.py:38-42
    Timestamp: 2026-01-15T15:05:49.557Z
    Learning: In Django projects, when using select_related() to traverse relations (for example, select_related("organization__config_settings")), the traversed relation must not be deferred. If you also use .only() in the same query, include the relation name or FK field (e.g., "organization" or "organization_id") in the .only() list to avoid the error "Field X cannot be both deferred and traversed using select_related at the same time." Apply this guideline to Django code in openwisp_controller/config/management/commands/clear_last_ip.py and similar modules by ensuring any select_related with an accompanying only() includes the related field names to prevent deferred/traversed conflicts.
    

    Applied to files:

    • openwisp_controller/config/tests/test_selenium.py
    📚 Learning: 2026-02-17T19:13:10.088Z
    Learnt from: nemesifier
    Repo: openwisp/openwisp-controller PR: 1175
    File: openwisp_controller/config/whois/commands.py:0-0
    Timestamp: 2026-02-17T19:13:10.088Z
    Learning: In reviews for the openwisp/openwisp-controller repository, do not propose changes based on Ruff warnings. The project does not use Ruff as its linter; ignore Ruff-related suggestions and follow the repository’s established linting and configuration rules. This guidance applies to all Python files under the openwisp_controller directory.
    

    Applied to files:

    • openwisp_controller/config/tests/test_selenium.py
    📚 Learning: 2026-01-15T15:07:17.354Z
    Learnt from: DragnEmperor
    Repo: openwisp/openwisp-controller PR: 1175
    File: openwisp_controller/geo/estimated_location/tests/tests.py:172-175
    Timestamp: 2026-01-15T15:07:17.354Z
    Learning: In this repository, flake8 enforces E501 (line too long) via setup.cfg (max-line-length = 88) while ruff ignores E501 via ruff.toml. Therefore, use '# noqa: E501' on lines that intentionally exceed 88 characters to satisfy flake8 without affecting ruff checks. This applies to Python files across the project (any .py) and is relevant for tests as well. Use sparingly and only where breaking lines is not feasible without hurting readability or functionality.
    

    Applied to files:

    • openwisp_controller/config/tests/test_selenium.py
    🧬 Code graph analysis (1)
    openwisp_controller/config/tests/test_selenium.py (2)
    openwisp_controller/config/tests/utils.py (3)
    • _create_template (77-87)
    • _create_config (60-73)
    • _create_config (396-401)
    openwisp_controller/geo/tests/test_selenium.py (1)
    • wait_for_presence (43-44)
    🔇 Additional comments (4)
    openwisp_controller/config/tests/test_selenium.py (4)

    4-4: LGTM!

    The import addition is appropriate for the new test that creates a custom permission group.


    45-59: LGTM - scoped selectors improve test reliability.

    The updated XPath selectors correctly scope template checkbox lookups to the ul.sortedm2m-items container, preventing false matches when multiple elements share the same value attribute. This aligns well with the JS fix targeting the specific sortedm2m container.


    467-475: DOM-based attribute verification is well-implemented.

    The test correctly uses Selenium's find_element and get_attribute methods to verify checkbox properties, addressing the prior review feedback about avoiding brittle page_source string matching.

    Note: The loop assumes template ordering by creation order. If the sortedm2m widget reorders templates (e.g., default templates first), the idx mapping may not align. Consider verifying by value lookup if ordering becomes inconsistent.


    401-481: Good test coverage for the duplicate templates bug.

    This test effectively validates the fix by:

    1. Setting up a limited-permission user (the bug's trigger condition)
    2. Creating shared templates that would previously appear duplicated
    3. Asserting exactly 2 items exist in the sortedm2m list (line 458-465)
    4. Verifying DOM attributes match expected values

    The test aligns with the retrieved learning that UI bugs should include Selenium browser tests.

    @openwisp-companion
    Copy link
    Copy Markdown

    Test Failure in test_add_mobile_location

    Hello @pandafy,
    (Analysis for commit 755cf1e)

    There is one test failure:

    • Test Failure: The test test_add_mobile_location in openwisp_controller.geo.tests.test_admin failed with an AssertionError: 0 != 1. This indicates that the count of locations with is_mobile=True was 0, but the test expected it to be 1.

    Fix:
    Review the test setup and the logic within test_add_mobile_location to ensure that a mobile location is correctly created and counted. It's possible that the test data setup or the assertion logic needs adjustment.

    pandafy added 2 commits March 27, 2026 10:55
    Bug:
    The JS logic in relevant_templates.js assumed that the last
    `ul.sortedm2m-items` element belonged to the empty inline form used by
    Django admin formsets. This assumption breaks when the user does not
    have permission to add Config objects: in that case the
    ConfigInlineAdmin does not render the empty form.
    
    As a result, both selectors ended up referencing the same list and the
    script appended template elements twice to the same `sortedm2m` list,
    causing duplicate entries and issues when saving the form.
    
    Fix:
    Select the empty form container explicitly using `#config-empty
    ul.sortedm2m-items` instead of relying on the last occurrence of
    `ul.sortedm2m-items`. This ensures the logic works correctly regardless
    of whether the empty inline form is rendered.
    
    [backport 1.2]
    @pandafy pandafy force-pushed the fix-relevant-templates branch from 755cf1e to ed364bc Compare March 27, 2026 05:25
    Copy link
    Copy Markdown
    Contributor

    @coderabbitai coderabbitai bot left a comment

    Choose a reason for hiding this comment

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

    Actionable comments posted: 1

    ♻️ Duplicate comments (1)
    openwisp_controller/config/tests/test_selenium.py (1)

    444-446: ⚠️ Potential issue | 🟡 Minor

    Use self.config_app_label for URL pattern consistency.

    Other tests in this class use f"admin:{self.config_app_label}_device_change" (e.g., lines 72, 213, 278), but this test hardcodes "admin:config_device_change". For consistency and to support downstream projects that extend and reuse this test suite with custom app labels, use the class attribute.

    🔧 Proposed fix
             self.open(
    -            reverse("admin:config_device_change", args=[device.id]) + "#config-group"
    +            reverse(f"admin:{self.config_app_label}_device_change", args=[device.id]) + "#config-group"
             )
    🤖 Prompt for AI Agents
    Verify each finding against the current code and only fix it if needed.
    
    In `@openwisp_controller/config/tests/test_selenium.py` around lines 444 - 446,
    Replace the hardcoded admin URL pattern "admin:config_device_change" with the
    class attribute-based pattern that uses self.config_app_label so the test uses
    the same dynamic app label as other tests; update the call to reverse (the
    reverse(...) invocation in the test) to construct the pattern using
    f"admin:{self.config_app_label}_device_change" and keep the existing args and
    fragment ("#config-group") intact.
    
    🤖 Prompt for all review comments with AI agents
    Verify each finding against the current code and only fix it if needed.
    
    Inline comments:
    In `@openwisp_controller/geo/tests/test_selenium.py`:
    - Around line 94-97: The admin URL is reversed with the wrong app label (using
    self.app_label which is "geo"), causing a NoReverseMatch; change the reverse
    call to use the Device's actual admin app label ("config") or derive it from the
    model (e.g., self.object_model._meta.app_label or the device instance's
    _meta.app_label) so the pattern becomes "admin:config_<modelname>_change" when
    calling reverse with args=[ol.device.id]; update the call that constructs path
    (currently using
    reverse(f"admin:{self.app_label}_{self.object_model._meta.model_name}_change",
    args=[ol.device.id])) to use the correct app_label.
    
    ---
    
    Duplicate comments:
    In `@openwisp_controller/config/tests/test_selenium.py`:
    - Around line 444-446: Replace the hardcoded admin URL pattern
    "admin:config_device_change" with the class attribute-based pattern that uses
    self.config_app_label so the test uses the same dynamic app label as other
    tests; update the call to reverse (the reverse(...) invocation in the test) to
    construct the pattern using f"admin:{self.config_app_label}_device_change" and
    keep the existing args and fragment ("#config-group") intact.
    
    🪄 Autofix (Beta)

    Fix all unresolved CodeRabbit comments on this PR:

    • Push a commit to this branch (recommended)
    • Create a new PR with the fixes

    ℹ️ Review info
    ⚙️ Run configuration

    Configuration used: Organization UI

    Review profile: ASSERTIVE

    Plan: Pro

    Run ID: bc1c75dc-a2ca-4694-ae30-867b759002d0

    📥 Commits

    Reviewing files that changed from the base of the PR and between 755cf1e and ed364bc.

    📒 Files selected for processing (3)
    • openwisp_controller/config/static/config/js/relevant_templates.js
    • openwisp_controller/config/tests/test_selenium.py
    • openwisp_controller/geo/tests/test_selenium.py
    📜 Review details
    🧰 Additional context used
    📓 Path-based instructions (4)
    **/*.{js,ts,tsx,jsx,py,java,go,cs,rb,php,c,cpp,h,hpp}

    📄 CodeRabbit inference engine (Custom checks)

    **/*.{js,ts,tsx,jsx,py,java,go,cs,rb,php,c,cpp,h,hpp}: Flag potential security vulnerabilities in code
    Avoid unnecessary comments or docstrings for code that is already clear
    Code formatting is compact and readable. Do not add excessive blank lines, especially inside function or method bodies
    Flag unused or redundant code
    Ensure variables, functions, classes, and files have descriptive and consistent names
    New code must handle errors properly: log errors that cannot be resolved by the user with error level, log unusual conditions with warning level, log important background actions with info level, and provide user-facing messages for errors that the user can solve autonomously

    Files:

    • openwisp_controller/geo/tests/test_selenium.py
    • openwisp_controller/config/static/config/js/relevant_templates.js
    • openwisp_controller/config/tests/test_selenium.py
    **/*.{js,ts,tsx,jsx,py,java,go,cs,rb,php,c,cpp,h,hpp,sql}

    📄 CodeRabbit inference engine (Custom checks)

    Flag obvious performance regressions, such as heavy loops, repeated I/O, or unoptimized queries

    Files:

    • openwisp_controller/geo/tests/test_selenium.py
    • openwisp_controller/config/static/config/js/relevant_templates.js
    • openwisp_controller/config/tests/test_selenium.py
    **/*.{js,ts,tsx,jsx,py,java,go,cs,rb,php,c,cpp,h,hpp,sh,bash,sql}

    📄 CodeRabbit inference engine (Custom checks)

    Cryptic or non-obvious code (regex, complex bash commands, or hard-to-read code) must include a concise comment explaining why it is needed and why the complexity is acceptable

    Files:

    • openwisp_controller/geo/tests/test_selenium.py
    • openwisp_controller/config/static/config/js/relevant_templates.js
    • openwisp_controller/config/tests/test_selenium.py
    **/*.{py,html}

    📄 CodeRabbit inference engine (Custom checks)

    For Django pull requests, ensure all user-facing strings are marked as translatable using the Django i18n framework

    Files:

    • openwisp_controller/geo/tests/test_selenium.py
    • openwisp_controller/config/tests/test_selenium.py
    🧠 Learnings (6)
    📚 Learning: 2026-01-12T22:27:48.342Z
    Learnt from: nemesifier
    Repo: openwisp/openwisp-controller PR: 1175
    File: tests/openwisp2/sample_config/migrations/0008_whoisinfo_organizationconfigsettings_whois_enabled.py:18-67
    Timestamp: 2026-01-12T22:27:48.342Z
    Learning: In tests/openwisp2/sample_config/models.py and corresponding test migrations, the WHOISInfo model intentionally includes an additional "details" field not present in the base AbstractWHOISInfo model. This is a testing pattern to verify that swappable models (CONFIG_WHOISINFO_MODEL) can be extended with custom fields without errors.
    

    Applied to files:

    • openwisp_controller/geo/tests/test_selenium.py
    📚 Learning: 2026-01-15T15:05:49.557Z
    Learnt from: DragnEmperor
    Repo: openwisp/openwisp-controller PR: 1175
    File: openwisp_controller/config/management/commands/clear_last_ip.py:38-42
    Timestamp: 2026-01-15T15:05:49.557Z
    Learning: In Django projects, when using select_related() to traverse relations (for example, select_related("organization__config_settings")), the traversed relation must not be deferred. If you also use .only() in the same query, include the relation name or FK field (e.g., "organization" or "organization_id") in the .only() list to avoid the error "Field X cannot be both deferred and traversed using select_related at the same time." Apply this guideline to Django code in openwisp_controller/config/management/commands/clear_last_ip.py and similar modules by ensuring any select_related with an accompanying only() includes the related field names to prevent deferred/traversed conflicts.
    

    Applied to files:

    • openwisp_controller/geo/tests/test_selenium.py
    • openwisp_controller/config/tests/test_selenium.py
    📚 Learning: 2026-02-17T19:13:10.088Z
    Learnt from: nemesifier
    Repo: openwisp/openwisp-controller PR: 1175
    File: openwisp_controller/config/whois/commands.py:0-0
    Timestamp: 2026-02-17T19:13:10.088Z
    Learning: In reviews for the openwisp/openwisp-controller repository, do not propose changes based on Ruff warnings. The project does not use Ruff as its linter; ignore Ruff-related suggestions and follow the repository’s established linting and configuration rules. This guidance applies to all Python files under the openwisp_controller directory.
    

    Applied to files:

    • openwisp_controller/geo/tests/test_selenium.py
    • openwisp_controller/config/tests/test_selenium.py
    📚 Learning: 2026-01-15T15:07:17.354Z
    Learnt from: DragnEmperor
    Repo: openwisp/openwisp-controller PR: 1175
    File: openwisp_controller/geo/estimated_location/tests/tests.py:172-175
    Timestamp: 2026-01-15T15:07:17.354Z
    Learning: In this repository, flake8 enforces E501 (line too long) via setup.cfg (max-line-length = 88) while ruff ignores E501 via ruff.toml. Therefore, use '# noqa: E501' on lines that intentionally exceed 88 characters to satisfy flake8 without affecting ruff checks. This applies to Python files across the project (any .py) and is relevant for tests as well. Use sparingly and only where breaking lines is not feasible without hurting readability or functionality.
    

    Applied to files:

    • openwisp_controller/geo/tests/test_selenium.py
    • openwisp_controller/config/tests/test_selenium.py
    📚 Learning: 2026-03-14T19:34:33.773Z
    Learnt from: CR
    Repo: openwisp/openwisp-controller PR: 0
    File: coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt:0-0
    Timestamp: 2026-03-14T19:34:33.773Z
    Learning: Applies to **/*.{e2e,browser,selenium}.{js,ts,tsx,jsx} : If a bug affects the user interface, include a Selenium browser test; if missing, raise a warning
    

    Applied to files:

    • openwisp_controller/config/tests/test_selenium.py
    📚 Learning: 2026-03-14T19:34:33.773Z
    Learnt from: CR
    Repo: openwisp/openwisp-controller PR: 0
    File: coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt:0-0
    Timestamp: 2026-03-14T19:34:33.773Z
    Learning: Applies to **/*{.test,.spec,_test,test_}.{js,ts,tsx,jsx,py,java,go,cs,rb} : Tests must be updated to cover non-trivial changes and ensure proper validation of modified behavior
    

    Applied to files:

    • openwisp_controller/config/tests/test_selenium.py
    🔇 Additional comments (4)
    openwisp_controller/config/static/config/js/relevant_templates.js (1)

    140-141: LGTM! The selector fix correctly targets the empty form container.

    Changing from :last to #config-empty ul.sortedm2m-items ensures prefix elements are only appended to the empty inline form when it exists. When users lack add permission and #config-empty isn't rendered, the jQuery selector returns an empty set and append() becomes a no-op, preventing duplicates.

    openwisp_controller/config/tests/test_selenium.py (3)

    4-4: LGTM!

    Import addition is required for the new test that creates a custom permission group.


    45-59: LGTM! Scoped XPath improves test reliability.

    The updated XPath //ul[contains(@Class,"sortedm2m-items")]//input[@value="..."] correctly scopes checkbox lookups to the sortedm2m widget container, preventing false matches from other page elements and aligning with the JS fix.


    401-481: Good test coverage for the duplicate templates bug.

    The test properly validates the fix by:

    1. Creating a user without add_config permission (the trigger condition)
    2. Verifying exactly 2 template items in the sortedm2m list (no duplicates)
    3. Using DOM-based attribute assertions for checkbox verification
    4. Confirming the save operation completes successfully

    @openwisp-companion
    Copy link
    Copy Markdown

    Test Failures in OpenWISP Controller CI

    Hello @pandafy,
    (Analysis for commit ed364bc)

    1. Test Failure: openwisp_controller.subnet.tests.test_admin.TestTransactionDeviceAdmin.test_vpn_template_switch_checksum_db failed with openwisp_controller.config.models.Config.DoesNotExist: Config matching query does not exist.
    • Fix: The test test_vpn_template_switch_checksum_db in openwisp_controller/subnet/tests/test_admin.py is trying to access a Config object that does not exist. Ensure that a Config object is created before this test runs, or adjust the test to handle the case where it might not exist.
    1. Test Failure: openwisp_controller.geo.tests.test_selenium.TestDeviceAdminReadonly.test_unsaved_changes_readonly failed with django.urls.exceptions.NoReverseMatch: Reverse for 'geo_device_change' not found: 'geo_device_change' is not a valid view function or pattern name.
    • Fix: The test test_unsaved_changes_readonly in openwisp_controller/geo/tests/test_selenium.py is attempting to reverse a URL named geo_device_change which is not defined in the openwisp_controller/urls.py or openwisp_controller/geo/api/urls.py. Ensure that the URL name geo_device_change is correctly defined in the URL patterns or update the test to use the correct URL name.
    1. Test Failure: django.db.utils.IntegrityError: FOREIGN KEY constraint failed occurred during a Selenium test (openwisp_controller.geo.tests.test_selenium.TestDeviceAdminReadonly.test_unsaved_changes_readonly was retried 5 times). This error typically indicates that a record is being inserted or updated with a foreign key that points to a non-existent record.
    • Fix: This is likely related to the NoReverseMatch error. The FOREIGN KEY constraint failed suggests an issue with data integrity during the test setup or execution. Review the test setup in openwisp_controller/geo/tests/test_selenium.py and ensure that all related objects (like Device, Location, FloorPlan, DeviceLocation) are created and properly linked before the test attempts to modify them. Specifically, check the test_unsaved_changes_readonly test and its dependencies.
    1. WHOIS Lookup Failures: Multiple WHOIS lookup failed errors were reported, including issues with account limits, authentication, and permissions for the GeoIP2 service.
    • Fix: These errors indicate a problem with the external WHOIS/GeoIP2 service configuration or usage. This is likely an infrastructure or configuration issue outside the scope of the code changes. The CI environment might have issues accessing or using this service.
    1. Runtime Warnings: Several RuntimeWarning: DateTimeField ... received a naive datetime while time zone support is active. warnings were observed.
    • Fix: This is a warning, not a failure, but it indicates potential issues with how datetime objects are handled. Ensure that all datetime fields are timezone-aware, especially when interacting with the database or external services. This might involve using timezone.now() consistently and ensuring timezone settings are correctly configured.

    @pandafy pandafy force-pushed the fix-relevant-templates branch from ed364bc to 83f4005 Compare March 27, 2026 07:28
    @openwisp-companion
    Copy link
    Copy Markdown

    Test Failures Detected

    Hello @pandafy,
    (Analysis for commit ed364bc)

    1. Test Failure: django.urls.exceptions.NoReverseMatch: Reverse for 'geo_device_change' not found.
    • Reason: The test test_unsaved_changes_readonly in openwisp_controller.geo.tests.test_selenium is trying to reverse a URL named geo_device_change, but this URL pattern is not defined in the project's URL configuration.
    • Fix: Ensure that the geo_device_change URL pattern is correctly defined in openwisp_controller.geo.urls and included in the main urls.py. If this URL is not intended to be used, remove the reference from the test.
    1. Test Failure: sqlite3.IntegrityError: FOREIGN KEY constraint failed
    • Reason: This indicates a violation of a foreign key constraint during a database operation. The traceback points to openwisp_controller.connection.base.models.py within the DeviceConnection.get_working_connection method, specifically when trying to save a DeviceConnection or related model. This often happens when trying to create or update a record with a foreign key that points to a non-existent record in the related table.
    • Fix: Investigate the test that triggers this failure (An exception was raised while executing command b4049a5a-e65e-4bd3-be10-d5d40c80e15c). Ensure that all necessary related objects (like Device or Organization) exist in the database before the operation that causes the integrity error. The test retries suggest a potential race condition or a setup issue in the test environment.
    1. RuntimeWarning: DateTimeField ... received a naive datetime while time zone support is active.
    • Reason: Several RuntimeWarning messages indicate that DateTimeFields are receiving naive datetime objects when timezone support is enabled. This can lead to unexpected behavior with date and time comparisons.
    • Fix: Ensure that all datetime objects being saved to the database are timezone-aware. This typically involves using django.utils.timezone.now() or making sure that any datetime objects created are properly localized. This issue appears in multiple tests related to Ca.validity_start and Cert.validity_start.
    1. UnorderedObjectListWarning: Pagination may yield inconsistent results with an unordered object_list
    • Reason: This warning suggests that queries used for pagination in the Django admin are not explicitly ordered. This can lead to inconsistent results if the order of items changes between paginated pages.
    • Fix: Add .order_by() to the relevant QuerySets in the Django admin configuration or in the views that generate these QuerySets to ensure a consistent order. This warning appears in openwisp_controller.pki.models.Ca and openwisp_controller.pki.models.Cert.
    1. WHOIS lookup failed: Multiple errors related to WHOIS lookups failing due to invalid credentials, no information found, or account issues.
    • Reason: The OPENWISP_CONTROLLER_WHOIS_GEOIP_ACCOUNT and OPENWISP_CONTROLLER_WHOIS_GEOIP_KEY settings are either missing, invalid, or the account has run out of queries.
    • Fix: Check and correct the OPENWISP_CONTROLLER_WHOIS_GEOIP_ACCOUNT and OPENWISP_CONTROLLER_WHOIS_GEOIP_KEY settings in your environment configuration. Ensure the account has sufficient query credits. If WHOIS lookups are not critical for this test, consider disabling OPENWISP_CONTROLLER_WHOIS_ENABLED or mocking the WHOIS service in the test.

    @pandafy
    Copy link
    Copy Markdown
    Member Author

    pandafy commented Mar 27, 2026

    @coderabbitai review!

    @coderabbitai
    Copy link
    Copy Markdown
    Contributor

    coderabbitai bot commented Mar 27, 2026

    @pandafy Sure, I'll review the changes now!

    ✅ Actions performed

    Review triggered.

    Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

    Copy link
    Copy Markdown
    Contributor

    @coderabbitai coderabbitai bot left a comment

    Choose a reason for hiding this comment

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

    ♻️ Duplicate comments (1)
    openwisp_controller/config/tests/test_selenium.py (1)

    444-446: ⚠️ Potential issue | 🟠 Major

    Use self.config_app_label here instead of hardcoding config.

    This reintroduces app-label coupling in a test path that should stay swappable for downstream integrations.

    🔧 Proposed fix
             self.open(
    -            reverse("admin:config_device_change", args=[device.id]) + "#config-group"
    +            reverse(
    +                f"admin:{self.config_app_label}_device_change", args=[device.id]
    +            )
    +            + "#config-group"
             )
    🤖 Prompt for AI Agents
    Verify each finding against the current code and only fix it if needed.
    
    In `@openwisp_controller/config/tests/test_selenium.py` around lines 444 - 446,
    The test currently hardcodes the app label in the admin URL reverse call
    (reverse("admin:config_device_change", ...)), which breaks downstream
    swappability; change the URL name to use the instance attribute
    self.config_app_label so the call becomes
    reverse(f"admin:{self.config_app_label}_device_change", args=[device.id]) (i.e.,
    replace the literal "config" with self.config_app_label) in the test method that
    calls self.open().
    
    🤖 Prompt for all review comments with AI agents
    Verify each finding against the current code and only fix it if needed.
    
    Duplicate comments:
    In `@openwisp_controller/config/tests/test_selenium.py`:
    - Around line 444-446: The test currently hardcodes the app label in the admin
    URL reverse call (reverse("admin:config_device_change", ...)), which breaks
    downstream swappability; change the URL name to use the instance attribute
    self.config_app_label so the call becomes
    reverse(f"admin:{self.config_app_label}_device_change", args=[device.id]) (i.e.,
    replace the literal "config" with self.config_app_label) in the test method that
    calls self.open().
    

    ℹ️ Review info
    ⚙️ Run configuration

    Configuration used: Organization UI

    Review profile: ASSERTIVE

    Plan: Pro

    Run ID: 2d1884c6-cbc1-4351-8115-b497462f0e21

    📥 Commits

    Reviewing files that changed from the base of the PR and between 755cf1e and 83f4005.

    📒 Files selected for processing (3)
    • openwisp_controller/config/static/config/js/relevant_templates.js
    • openwisp_controller/config/tests/test_selenium.py
    • openwisp_controller/geo/tests/test_selenium.py
    📜 Review details
    🧰 Additional context used
    📓 Path-based instructions (4)
    **/*.{js,ts,tsx,jsx,py,java,go,cs,rb,php,c,cpp,h,hpp}

    📄 CodeRabbit inference engine (Custom checks)

    **/*.{js,ts,tsx,jsx,py,java,go,cs,rb,php,c,cpp,h,hpp}: Flag potential security vulnerabilities in code
    Avoid unnecessary comments or docstrings for code that is already clear
    Code formatting is compact and readable. Do not add excessive blank lines, especially inside function or method bodies
    Flag unused or redundant code
    Ensure variables, functions, classes, and files have descriptive and consistent names
    New code must handle errors properly: log errors that cannot be resolved by the user with error level, log unusual conditions with warning level, log important background actions with info level, and provide user-facing messages for errors that the user can solve autonomously

    Files:

    • openwisp_controller/config/static/config/js/relevant_templates.js
    • openwisp_controller/geo/tests/test_selenium.py
    • openwisp_controller/config/tests/test_selenium.py
    **/*.{js,ts,tsx,jsx,py,java,go,cs,rb,php,c,cpp,h,hpp,sql}

    📄 CodeRabbit inference engine (Custom checks)

    Flag obvious performance regressions, such as heavy loops, repeated I/O, or unoptimized queries

    Files:

    • openwisp_controller/config/static/config/js/relevant_templates.js
    • openwisp_controller/geo/tests/test_selenium.py
    • openwisp_controller/config/tests/test_selenium.py
    **/*.{js,ts,tsx,jsx,py,java,go,cs,rb,php,c,cpp,h,hpp,sh,bash,sql}

    📄 CodeRabbit inference engine (Custom checks)

    Cryptic or non-obvious code (regex, complex bash commands, or hard-to-read code) must include a concise comment explaining why it is needed and why the complexity is acceptable

    Files:

    • openwisp_controller/config/static/config/js/relevant_templates.js
    • openwisp_controller/geo/tests/test_selenium.py
    • openwisp_controller/config/tests/test_selenium.py
    **/*.{py,html}

    📄 CodeRabbit inference engine (Custom checks)

    For Django pull requests, ensure all user-facing strings are marked as translatable using the Django i18n framework

    Files:

    • openwisp_controller/geo/tests/test_selenium.py
    • openwisp_controller/config/tests/test_selenium.py
    🧠 Learnings (5)
    📚 Learning: 2026-01-15T15:05:49.557Z
    Learnt from: DragnEmperor
    Repo: openwisp/openwisp-controller PR: 1175
    File: openwisp_controller/config/management/commands/clear_last_ip.py:38-42
    Timestamp: 2026-01-15T15:05:49.557Z
    Learning: In Django projects, when using select_related() to traverse relations (for example, select_related("organization__config_settings")), the traversed relation must not be deferred. If you also use .only() in the same query, include the relation name or FK field (e.g., "organization" or "organization_id") in the .only() list to avoid the error "Field X cannot be both deferred and traversed using select_related at the same time." Apply this guideline to Django code in openwisp_controller/config/management/commands/clear_last_ip.py and similar modules by ensuring any select_related with an accompanying only() includes the related field names to prevent deferred/traversed conflicts.
    

    Applied to files:

    • openwisp_controller/geo/tests/test_selenium.py
    • openwisp_controller/config/tests/test_selenium.py
    📚 Learning: 2026-02-17T19:13:10.088Z
    Learnt from: nemesifier
    Repo: openwisp/openwisp-controller PR: 1175
    File: openwisp_controller/config/whois/commands.py:0-0
    Timestamp: 2026-02-17T19:13:10.088Z
    Learning: In reviews for the openwisp/openwisp-controller repository, do not propose changes based on Ruff warnings. The project does not use Ruff as its linter; ignore Ruff-related suggestions and follow the repository’s established linting and configuration rules. This guidance applies to all Python files under the openwisp_controller directory.
    

    Applied to files:

    • openwisp_controller/geo/tests/test_selenium.py
    • openwisp_controller/config/tests/test_selenium.py
    📚 Learning: 2026-01-15T15:07:17.354Z
    Learnt from: DragnEmperor
    Repo: openwisp/openwisp-controller PR: 1175
    File: openwisp_controller/geo/estimated_location/tests/tests.py:172-175
    Timestamp: 2026-01-15T15:07:17.354Z
    Learning: In this repository, flake8 enforces E501 (line too long) via setup.cfg (max-line-length = 88) while ruff ignores E501 via ruff.toml. Therefore, use '# noqa: E501' on lines that intentionally exceed 88 characters to satisfy flake8 without affecting ruff checks. This applies to Python files across the project (any .py) and is relevant for tests as well. Use sparingly and only where breaking lines is not feasible without hurting readability or functionality.
    

    Applied to files:

    • openwisp_controller/geo/tests/test_selenium.py
    • openwisp_controller/config/tests/test_selenium.py
    📚 Learning: 2026-03-14T19:34:33.773Z
    Learnt from: CR
    Repo: openwisp/openwisp-controller PR: 0
    File: coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt:0-0
    Timestamp: 2026-03-14T19:34:33.773Z
    Learning: Applies to **/*.{e2e,browser,selenium}.{js,ts,tsx,jsx} : If a bug affects the user interface, include a Selenium browser test; if missing, raise a warning
    

    Applied to files:

    • openwisp_controller/config/tests/test_selenium.py
    📚 Learning: 2026-03-14T19:34:33.773Z
    Learnt from: CR
    Repo: openwisp/openwisp-controller PR: 0
    File: coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt:0-0
    Timestamp: 2026-03-14T19:34:33.773Z
    Learning: Applies to **/*{.test,.spec,_test,test_}.{js,ts,tsx,jsx,py,java,go,cs,rb} : Tests must be updated to cover non-trivial changes and ensure proper validation of modified behavior
    

    Applied to files:

    • openwisp_controller/config/tests/test_selenium.py
    🔇 Additional comments (3)
    openwisp_controller/geo/tests/test_selenium.py (1)

    94-98: Good fix: admin URL now derives from model metadata.

    This avoids app-label mismatches and keeps the Selenium test resilient to model/admin label differences.

    openwisp_controller/config/static/config/js/relevant_templates.js (1)

    141-141: Selector change is correct and fixes the duplication root cause.

    Using #config-empty ul.sortedm2m-items removes the brittle “last list” assumption and prevents double-appending to the same widget.

    openwisp_controller/config/tests/test_selenium.py (1)

    49-59: Nice improvement: template visibility lookup is now properly scoped.

    Constraining XPath under ul.sortedm2m-items reduces false matches from unrelated inputs.

    @pandafy pandafy force-pushed the fix-relevant-templates branch from 83f4005 to b9f6f1b Compare March 27, 2026 08:31
    @pandafy
    Copy link
    Copy Markdown
    Member Author

    pandafy commented Mar 27, 2026

    @coderabbitai review!

    @coderabbitai
    Copy link
    Copy Markdown
    Contributor

    coderabbitai bot commented Mar 27, 2026

    @pandafy Sure, I'll review the changes now!

    ✅ Actions performed

    Review triggered.

    Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

    Copy link
    Copy Markdown
    Contributor

    @coderabbitai coderabbitai bot left a comment

    Choose a reason for hiding this comment

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

    Actionable comments posted: 1

    🤖 Prompt for all review comments with AI agents
    Verify each finding against the current code and only fix it if needed.
    
    Inline comments:
    In `@openwisp_controller/config/tests/test_selenium.py`:
    - Around line 401-483: The test_relevant_templates_duplicates test must
    explicitly assert the precondition that no empty inline add form exists (so the
    bug branch is exercised); before calling _verify_templates_visibility (or any
    checks of the rendered items) add an assertion that the element with id
    "config-empty" is not present (or equivalently that the inline add form is
    unavailable) using the test's Selenium helpers (e.g., find_element/find_elements
    or wait_for_absence) to fail fast if the empty inline is present; this ensures
    the test actually covers the case where the empty inline form is missing and
    prevents the permission fixture from masking the regression.
    
    🪄 Autofix (Beta)

    Fix all unresolved CodeRabbit comments on this PR:

    • Push a commit to this branch (recommended)
    • Create a new PR with the fixes

    ℹ️ Review info
    ⚙️ Run configuration

    Configuration used: Organization UI

    Review profile: ASSERTIVE

    Plan: Pro

    Run ID: 904eb428-2a48-482c-8414-3475d5d3f0c0

    📥 Commits

    Reviewing files that changed from the base of the PR and between 83f4005 and b9f6f1b.

    📒 Files selected for processing (2)
    • openwisp_controller/config/tests/test_selenium.py
    • openwisp_controller/geo/tests/test_selenium.py
    📜 Review details
    🧰 Additional context used
    📓 Path-based instructions (4)
    **/*.{js,ts,tsx,jsx,py,java,go,cs,rb,php,c,cpp,h,hpp}

    📄 CodeRabbit inference engine (Custom checks)

    **/*.{js,ts,tsx,jsx,py,java,go,cs,rb,php,c,cpp,h,hpp}: Flag potential security vulnerabilities in code
    Avoid unnecessary comments or docstrings for code that is already clear
    Code formatting is compact and readable. Do not add excessive blank lines, especially inside function or method bodies
    Flag unused or redundant code
    Ensure variables, functions, classes, and files have descriptive and consistent names
    New code must handle errors properly: log errors that cannot be resolved by the user with error level, log unusual conditions with warning level, log important background actions with info level, and provide user-facing messages for errors that the user can solve autonomously

    Files:

    • openwisp_controller/geo/tests/test_selenium.py
    • openwisp_controller/config/tests/test_selenium.py
    **/*.{js,ts,tsx,jsx,py,java,go,cs,rb,php,c,cpp,h,hpp,sql}

    📄 CodeRabbit inference engine (Custom checks)

    Flag obvious performance regressions, such as heavy loops, repeated I/O, or unoptimized queries

    Files:

    • openwisp_controller/geo/tests/test_selenium.py
    • openwisp_controller/config/tests/test_selenium.py
    **/*.{js,ts,tsx,jsx,py,java,go,cs,rb,php,c,cpp,h,hpp,sh,bash,sql}

    📄 CodeRabbit inference engine (Custom checks)

    Cryptic or non-obvious code (regex, complex bash commands, or hard-to-read code) must include a concise comment explaining why it is needed and why the complexity is acceptable

    Files:

    • openwisp_controller/geo/tests/test_selenium.py
    • openwisp_controller/config/tests/test_selenium.py
    **/*.{py,html}

    📄 CodeRabbit inference engine (Custom checks)

    For Django pull requests, ensure all user-facing strings are marked as translatable using the Django i18n framework

    Files:

    • openwisp_controller/geo/tests/test_selenium.py
    • openwisp_controller/config/tests/test_selenium.py
    🧠 Learnings (6)
    📚 Learning: 2026-01-12T22:27:48.342Z
    Learnt from: nemesifier
    Repo: openwisp/openwisp-controller PR: 1175
    File: tests/openwisp2/sample_config/migrations/0008_whoisinfo_organizationconfigsettings_whois_enabled.py:18-67
    Timestamp: 2026-01-12T22:27:48.342Z
    Learning: In tests/openwisp2/sample_config/models.py and corresponding test migrations, the WHOISInfo model intentionally includes an additional "details" field not present in the base AbstractWHOISInfo model. This is a testing pattern to verify that swappable models (CONFIG_WHOISINFO_MODEL) can be extended with custom fields without errors.
    

    Applied to files:

    • openwisp_controller/geo/tests/test_selenium.py
    📚 Learning: 2026-01-15T15:05:49.557Z
    Learnt from: DragnEmperor
    Repo: openwisp/openwisp-controller PR: 1175
    File: openwisp_controller/config/management/commands/clear_last_ip.py:38-42
    Timestamp: 2026-01-15T15:05:49.557Z
    Learning: In Django projects, when using select_related() to traverse relations (for example, select_related("organization__config_settings")), the traversed relation must not be deferred. If you also use .only() in the same query, include the relation name or FK field (e.g., "organization" or "organization_id") in the .only() list to avoid the error "Field X cannot be both deferred and traversed using select_related at the same time." Apply this guideline to Django code in openwisp_controller/config/management/commands/clear_last_ip.py and similar modules by ensuring any select_related with an accompanying only() includes the related field names to prevent deferred/traversed conflicts.
    

    Applied to files:

    • openwisp_controller/geo/tests/test_selenium.py
    • openwisp_controller/config/tests/test_selenium.py
    📚 Learning: 2026-02-17T19:13:10.088Z
    Learnt from: nemesifier
    Repo: openwisp/openwisp-controller PR: 1175
    File: openwisp_controller/config/whois/commands.py:0-0
    Timestamp: 2026-02-17T19:13:10.088Z
    Learning: In reviews for the openwisp/openwisp-controller repository, do not propose changes based on Ruff warnings. The project does not use Ruff as its linter; ignore Ruff-related suggestions and follow the repository’s established linting and configuration rules. This guidance applies to all Python files under the openwisp_controller directory.
    

    Applied to files:

    • openwisp_controller/geo/tests/test_selenium.py
    • openwisp_controller/config/tests/test_selenium.py
    📚 Learning: 2026-01-15T15:07:17.354Z
    Learnt from: DragnEmperor
    Repo: openwisp/openwisp-controller PR: 1175
    File: openwisp_controller/geo/estimated_location/tests/tests.py:172-175
    Timestamp: 2026-01-15T15:07:17.354Z
    Learning: In this repository, flake8 enforces E501 (line too long) via setup.cfg (max-line-length = 88) while ruff ignores E501 via ruff.toml. Therefore, use '# noqa: E501' on lines that intentionally exceed 88 characters to satisfy flake8 without affecting ruff checks. This applies to Python files across the project (any .py) and is relevant for tests as well. Use sparingly and only where breaking lines is not feasible without hurting readability or functionality.
    

    Applied to files:

    • openwisp_controller/geo/tests/test_selenium.py
    • openwisp_controller/config/tests/test_selenium.py
    📚 Learning: 2026-03-14T19:34:33.773Z
    Learnt from: CR
    Repo: openwisp/openwisp-controller PR: 0
    File: coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt:0-0
    Timestamp: 2026-03-14T19:34:33.773Z
    Learning: Applies to **/*.{e2e,browser,selenium}.{js,ts,tsx,jsx} : If a bug affects the user interface, include a Selenium browser test; if missing, raise a warning
    

    Applied to files:

    • openwisp_controller/config/tests/test_selenium.py
    📚 Learning: 2026-03-14T19:34:33.773Z
    Learnt from: CR
    Repo: openwisp/openwisp-controller PR: 0
    File: coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt:0-0
    Timestamp: 2026-03-14T19:34:33.773Z
    Learning: Applies to **/*{.test,.spec,_test,test_}.{js,ts,tsx,jsx,py,java,go,cs,rb} : Tests must be updated to cover non-trivial changes and ensure proper validation of modified behavior
    

    Applied to files:

    • openwisp_controller/config/tests/test_selenium.py
    🔇 Additional comments (2)
    openwisp_controller/geo/tests/test_selenium.py (1)

    94-98: Good switch to model-derived admin routing.

    Using self.object_model._meta.app_label and model_name keeps this test aligned with the actual admin registration and swapped-model setups.

    openwisp_controller/config/tests/test_selenium.py (1)

    49-58: Good tightening of the template visibility locator.

    Scoping these checks to sortedm2m-items makes the assertions target the template widget instead of any matching input on the page.

    @openwisp-companion
    Copy link
    Copy Markdown

    Code Style and Test Failures

    Hello @pandafy,
    (Analysis for commit 592b3ed)

    There are two main issues in your commit:

    1. Code Style (Black and Flake8):
    • The Black check failed! error indicates that some code formatting is not compliant with the project's style guide.
    • The Flake8 check failed! error, specifically E501 line too long (90 > 88 characters), points to lines that exceed the maximum allowed length.

    Fix: Please run openwisp-qa-format in your local environment. This command will automatically fix most of the formatting issues. For the E501 errors, you'll need to manually adjust the line length by breaking it into multiple lines or rephrasing the code.

    1. Test Failure (Selenium):
    • The logs show a change in openwisp_controller/config/tests/test_selenium.py related to self.subTest. The way self.subTest is called has been updated to a more modern syntax, which is causing the test to fail.

    Fix: The change in the test log indicates that the self.subTest call needs to be updated. The diff shows the following change:

    -        with self.subTest("Regression precondition: empty Config inline is not rendered"):
    +        with self.subTest(
    +            "Regression precondition: empty Config inline is not rendered"
    +        ):

    Please update the self.subTest call in openwisp_controller/config/tests/test_selenium.py to match the new syntax.

    @pandafy pandafy force-pushed the fix-relevant-templates branch from 592b3ed to 4c9e834 Compare March 27, 2026 10:30
    @pandafy
    Copy link
    Copy Markdown
    Member Author

    pandafy commented Mar 27, 2026

    @coderabbitai review!

    @coderabbitai
    Copy link
    Copy Markdown
    Contributor

    coderabbitai bot commented Mar 27, 2026

    @pandafy Sure, I'll review the changes now!

    ✅ Actions performed

    Review triggered.

    Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

    Copy link
    Copy Markdown
    Contributor

    @coderabbitai coderabbitai bot left a comment

    Choose a reason for hiding this comment

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

    Actionable comments posted: 1

    🤖 Prompt for all review comments with AI agents
    Verify each finding against the current code and only fix it if needed.
    
    Inline comments:
    In `@openwisp_controller/config/tests/test_selenium.py`:
    - Around line 402-485: Remove the verbose docstring and redundant inline
    comments in the test that defines permission_codenames and creates the
    user/group/templates (the test containing permission_codenames, custom_group,
    user creation and calls to
    _create_template/_create_config/_verify_templates_visibility); keep only
    succinct comments for non-obvious logic (e.g., why organization=None is used)
    and preserve the subTest labels and assertions (the subTest blocks and selectors
    using find_elements/By.CSS_SELECTOR and the checkbox checks using
    id_config-templates_{idx}) so behavior is unchanged but noisy narration is
    eliminated.
    
    🪄 Autofix (Beta)

    Fix all unresolved CodeRabbit comments on this PR:

    • Push a commit to this branch (recommended)
    • Create a new PR with the fixes

    ℹ️ Review info
    ⚙️ Run configuration

    Configuration used: Organization UI

    Review profile: ASSERTIVE

    Plan: Pro

    Run ID: b6270880-d80e-48a9-8793-d4ba3a38b867

    📥 Commits

    Reviewing files that changed from the base of the PR and between b9f6f1b and 4c9e834.

    📒 Files selected for processing (1)
    • openwisp_controller/config/tests/test_selenium.py
    📜 Review details
    🧰 Additional context used
    📓 Path-based instructions (4)
    **/*.{js,ts,tsx,jsx,py,java,go,cs,rb,php,c,cpp,h,hpp}

    📄 CodeRabbit inference engine (Custom checks)

    **/*.{js,ts,tsx,jsx,py,java,go,cs,rb,php,c,cpp,h,hpp}: Flag potential security vulnerabilities in code
    Avoid unnecessary comments or docstrings for code that is already clear
    Code formatting is compact and readable. Do not add excessive blank lines, especially inside function or method bodies
    Flag unused or redundant code
    Ensure variables, functions, classes, and files have descriptive and consistent names
    New code must handle errors properly: log errors that cannot be resolved by the user with error level, log unusual conditions with warning level, log important background actions with info level, and provide user-facing messages for errors that the user can solve autonomously

    Files:

    • openwisp_controller/config/tests/test_selenium.py
    **/*.{js,ts,tsx,jsx,py,java,go,cs,rb,php,c,cpp,h,hpp,sql}

    📄 CodeRabbit inference engine (Custom checks)

    Flag obvious performance regressions, such as heavy loops, repeated I/O, or unoptimized queries

    Files:

    • openwisp_controller/config/tests/test_selenium.py
    **/*.{js,ts,tsx,jsx,py,java,go,cs,rb,php,c,cpp,h,hpp,sh,bash,sql}

    📄 CodeRabbit inference engine (Custom checks)

    Cryptic or non-obvious code (regex, complex bash commands, or hard-to-read code) must include a concise comment explaining why it is needed and why the complexity is acceptable

    Files:

    • openwisp_controller/config/tests/test_selenium.py
    **/*.{py,html}

    📄 CodeRabbit inference engine (Custom checks)

    For Django pull requests, ensure all user-facing strings are marked as translatable using the Django i18n framework

    Files:

    • openwisp_controller/config/tests/test_selenium.py
    🧠 Learnings (7)
    📚 Learning: 2026-03-14T19:34:33.773Z
    Learnt from: CR
    Repo: openwisp/openwisp-controller PR: 0
    File: coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt:0-0
    Timestamp: 2026-03-14T19:34:33.773Z
    Learning: Applies to **/*.{e2e,browser,selenium}.{js,ts,tsx,jsx} : If a bug affects the user interface, include a Selenium browser test; if missing, raise a warning
    

    Applied to files:

    • openwisp_controller/config/tests/test_selenium.py
    📚 Learning: 2026-03-14T19:34:33.773Z
    Learnt from: CR
    Repo: openwisp/openwisp-controller PR: 0
    File: coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt:0-0
    Timestamp: 2026-03-14T19:34:33.773Z
    Learning: Applies to **/*{.test,.spec,_test,test_}.{js,ts,tsx,jsx,py,java,go,cs,rb} : Tests must be updated to cover non-trivial changes and ensure proper validation of modified behavior
    

    Applied to files:

    • openwisp_controller/config/tests/test_selenium.py
    📚 Learning: 2026-03-14T19:34:33.773Z
    Learnt from: CR
    Repo: openwisp/openwisp-controller PR: 0
    File: coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt:0-0
    Timestamp: 2026-03-14T19:34:33.773Z
    Learning: Applies to **/*{.test,.spec,_test,test_}.{js,ts,tsx,jsx,py,java,go,cs,rb} : Regression test must fail if the patch is removed or commented out
    

    Applied to files:

    • openwisp_controller/config/tests/test_selenium.py
    📚 Learning: 2026-03-14T19:34:33.773Z
    Learnt from: CR
    Repo: openwisp/openwisp-controller PR: 0
    File: coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt:0-0
    Timestamp: 2026-03-14T19:34:33.773Z
    Learning: Applies to **/*{.test,.spec,_test,test_}.{js,ts,tsx,jsx,py,java,go,cs,rb} : Include a regression test for bug fixes that reproduces the bug scenario
    

    Applied to files:

    • openwisp_controller/config/tests/test_selenium.py
    📚 Learning: 2026-01-15T15:05:49.557Z
    Learnt from: DragnEmperor
    Repo: openwisp/openwisp-controller PR: 1175
    File: openwisp_controller/config/management/commands/clear_last_ip.py:38-42
    Timestamp: 2026-01-15T15:05:49.557Z
    Learning: In Django projects, when using select_related() to traverse relations (for example, select_related("organization__config_settings")), the traversed relation must not be deferred. If you also use .only() in the same query, include the relation name or FK field (e.g., "organization" or "organization_id") in the .only() list to avoid the error "Field X cannot be both deferred and traversed using select_related at the same time." Apply this guideline to Django code in openwisp_controller/config/management/commands/clear_last_ip.py and similar modules by ensuring any select_related with an accompanying only() includes the related field names to prevent deferred/traversed conflicts.
    

    Applied to files:

    • openwisp_controller/config/tests/test_selenium.py
    📚 Learning: 2026-02-17T19:13:10.088Z
    Learnt from: nemesifier
    Repo: openwisp/openwisp-controller PR: 1175
    File: openwisp_controller/config/whois/commands.py:0-0
    Timestamp: 2026-02-17T19:13:10.088Z
    Learning: In reviews for the openwisp/openwisp-controller repository, do not propose changes based on Ruff warnings. The project does not use Ruff as its linter; ignore Ruff-related suggestions and follow the repository’s established linting and configuration rules. This guidance applies to all Python files under the openwisp_controller directory.
    

    Applied to files:

    • openwisp_controller/config/tests/test_selenium.py
    📚 Learning: 2026-01-15T15:07:17.354Z
    Learnt from: DragnEmperor
    Repo: openwisp/openwisp-controller PR: 1175
    File: openwisp_controller/geo/estimated_location/tests/tests.py:172-175
    Timestamp: 2026-01-15T15:07:17.354Z
    Learning: In this repository, flake8 enforces E501 (line too long) via setup.cfg (max-line-length = 88) while ruff ignores E501 via ruff.toml. Therefore, use '# noqa: E501' on lines that intentionally exceed 88 characters to satisfy flake8 without affecting ruff checks. This applies to Python files across the project (any .py) and is relevant for tests as well. Use sparingly and only where breaking lines is not feasible without hurting readability or functionality.
    

    Applied to files:

    • openwisp_controller/config/tests/test_selenium.py
    🔇 Additional comments (2)
    openwisp_controller/config/tests/test_selenium.py (2)

    49-58: Widget-scoped locators make this helper safer.

    Confining the visibility checks to inputs under ul.sortedm2m-items keeps _verify_templates_visibility() aligned with the sortedm2m widget instead of any page element that happens to share the same value.


    449-487: Strong regression coverage for the missing-empty-inline path.

    Asserting that #config-empty is absent, then checking the rendered item count and checkbox attributes, makes the failure mode very explicit if the selector logic regresses again.

    Based on learnings: If a bug affects the user interface, include a Selenium browser test; include a regression test for bug fixes that reproduces the bug scenario.

    @nemesifier nemesifier merged commit b73e83a into master Mar 27, 2026
    21 checks passed
    @nemesifier nemesifier deleted the fix-relevant-templates branch March 27, 2026 16:25
    @github-project-automation github-project-automation bot moved this from In progress to Done in OpenWISP Contributor's Board Mar 27, 2026
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

    Labels

    None yet

    Projects

    Development

    Successfully merging this pull request may close these issues.

    3 participants