Skip to content

Fix RuboCop Capybara offenses in specs - #26516

Open
myabc wants to merge 3 commits into
release/18.0from
housekeeping/rubocop-capybara-fixes
Open

myabc wants to merge 3 commits into
release/18.0from
housekeeping/rubocop-capybara-fixes

Conversation

@myabc

@myabc myabc commented Nov 1, 2026 •

Copy link
Copy Markdown
Contributor

Ticket

Housekeeping, no work package.

Follows #26459 which bumped Rubocop Capybara

What are you trying to accomplish?

tl;dr for humans: Cleans up our browser tests so they follow the Capybara lint rules, which makes several of them less prone to passing or failing by timing luck.

Fixes every RuboCop Capybara and Capybara/RSpec offense in the specs. RuboCop now reports none for either namespace.

What approach did you choose and why?

The commits are split by risk, so each can be reviewed differently:

  1. Behaviour-neutral: aliases and equivalent options (have_content → have_text, have_selector → have_css, not_to have_x → to have_no_x, visible: false → visible: :all). Safe to skim.
  2. Changes how specs wait: first(...) instead of all(...)[0], have_current_path instead of reading current_url / current_path once, and a positive assertion before each negative assertion that directly follows visit. Worth a closer read.
  3. Specific finders, actions and matchers: find_field, click_button, have_field, have_button, have_select, have_link, and combined chained finds. find_field skips hidden and disabled fields by default, so those call sites pass type: "hidden" or disabled: explicitly.

Where a chained find filters the parent by text:, CSS cannot combine the selectors, so those use within instead.

AI involvement

Collaborative – AI generated a substantial part of the code; I reviewed and understand every line.

Merge checklist

  • Added/updated tests

@github-actions github-actions Bot added the ai: Collaborative 💻 AI generated a substantial part of the code; A human reviewed and understands every line. label Nov 2, 2026
Fixes RuboCop Capybara offenses where the replacement is an alias or
an equivalent option, so no spec changes what it checks or how long
it waits:

- Capybara/RSpec/HaveContent: `have_content` becomes `have_text`.
- Capybara/RSpec/HaveSelector: `have_selector` becomes `have_css`
  for CSS selectors.
- Capybara/RSpec/NegationMatcher: `not_to have_x` becomes
  `to have_no_x`.
- Capybara/VisibilityOption, Capybara/RSpec/VisibilityMatcher:
  `visible: false` becomes `visible: :all` and `visible: true`
  becomes `visible: :visible`.

Realigns the continuation lines that the shorter matcher names leave
out of alignment.
@myabc
myabc force-pushed the housekeeping/rubocop-capybara-fixes branch 2 times, most recently from ba99dd0 to 464aaf7 Compare November 2, 2026 00:51
@myabc
myabc changed the base branch from dev to release/18.0 November 2, 2026 15:03
@myabc myabc added needs review rubocop 👮 Just rubocop fixes labels Nov 2, 2026
@myabc
myabc marked this pull request as ready for review November 2, 2026 15:03
Copilot AI balanced review requested due to automatic review settings November 2, 2026 15:03
@github-actions

github-actions Bot commented Nov 2, 2026

Copy link
Copy Markdown

Warning

This pull request does not link an OpenProject work package.

Please add a link to the work package in the description, or reference it in the
title in square brackets, e.g. [SLUG-123] My title here.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 Approval recommended

No active review issues are reported for the Capybara lint updates to tests and shared helpers.

No open issues 🎉

What changed in this PR

Updates OpenProject’s specs and shared test helpers to follow the Capybara lint rules introduced by the RuboCop upgrade in #26459. Changes are confined to tests and test support, with additional synchronization intended to reduce timing-dependent results.

Changes:

  • Standardizes text/CSS matchers, negative assertions, and visibility options.
  • Uses waiting path matchers and positive page-load assertions before negative checks.
  • Replaces generic selectors with specific field/button helpers and simplifies scoped lookups, retaining a documented shadow-root exception.
File Description
spec/​views/​layouts/​base.html.erb_spec.rb Standardizes visibility options and login-link matching.
spec/​support/​workflows/​edit_helpers.rb Scopes status removal with within.
spec/​support/​toasts/​expectations.rb Dismisses toasts using the named close button.
spec/​support/​pages/​work_packages/​work_packages_timeline.rb Uses explicit visibility symbols.
spec/​support/​pages/​work_packages/​abstract_work_package.rb Uses a negative CSS matcher for loading completion.
spec/​support/​pages/​versions/​roadmap.rb Standardizes version text assertions.
spec/​support/​pages/​projects/​show.rb Standardizes dialog text matching.
spec/​support/​pages/​projects/​index.rb Uses explicit pagination-link visibility.
spec/​support/​pages/​members.rb Standardizes hidden-element visibility options.
spec/​support/​pages/​admin/​users/​index.rb Uses explicit filter-panel visibility.
spec/​support/​form_fields/​primerized/​input_field.rb Uses text and field-value matchers.
spec/​support/​form_fields/​primerized/​block_note_editor_input.rb Documents the CSS finder exception for shadow roots.
spec/​support/​form_fields/​primerized/​autocomplete_field.rb Scopes selected-option removal with within.
spec/​support/​form_fields/​input_form_field.rb Uses field matchers for values and presence.
spec/​support/​edit_fields/​work_package_status_field.rb Selects statuses with click_button.
spec/​support/​edit_fields/​edit_field.rb Standardizes display-text and inactive-field assertions.
spec/​support/​components/​work_packages/​group_by.rb Standardizes menu text matching.
spec/​support/​components/​work_packages/​filters.rb Standardizes visibility and negative CSS checks.
spec/​support/​components/​timelines/​timeline_row.rb Uses explicit visibility for timeline labels.
spec/​support/​components/​projects/​top_menu.rb Uses a negative CSS result matcher.
spec/​support/​components/​global_search.rb Uses a negative CSS closed-state matcher.
spec/​support/​components/​common/​inplace_edit_field.rb Standardizes calculation-error text matching.
spec/​support/​components/​common/​filters.rb Uses explicit filter-field visibility.
spec/​support/​components/​attachments_list.rb Standardizes deletion-confirmation text matching.
spec/​support/​components/​admin/​type_configuration_form.rb Uses explicit visibility when reading group order.
spec/​mailers/​user_mailer_spec.rb Standardizes email text assertions.
spec/​lib/​tabular_form_builder_spec.rb Uses select and button matchers.
spec/​lib/​primer/​open_project/​forms/​html_content_spec.rb Standardizes rendered-content text matching.
spec/​helpers/​settings_helper_spec.rb Uses checkbox field matchers with disabled-state filtering.
spec/​helpers/​no_results_helper_spec.rb Standardizes empty-state text assertions.
spec/​forms/​projects/​settings/​relations_form_spec.rb Uses a dedicated negative element matcher.
spec/​features/​workflows/​edit_multi_role_spec.rb Finds the search input by field type.
spec/​features/​work_packages/​tabs/​relations_children_spec.rb Standardizes child work-package text assertions.
spec/​features/​work_packages/​table/​queries/​query_menu_spec.rb Standardizes text checks and waits for URL changes.
spec/​features/​work_packages/​table/​queries/​filter_pagination_spec.rb Navigates pagination with click_button.
spec/​features/​work_packages/​table/​context_menu/​context_menu_shared_examples.rb Uses waiting URL matchers for child creation.
spec/​features/​work_packages/​reports_spec.rb Standardizes report text assertions.
spec/​features/​work_packages/​pagination_spec.rb Standardizes pagination content assertions.
spec/​features/​work_packages/​edit_work_package_spec.rb Standardizes journal-author text matching.
spec/​features/​work_packages/​details/​query_groups/​relation_query_group_spec.rb Uses named buttons for relation actions.
spec/​features/​work_packages/​details/​markdown/​todolist_spec.rb Uses first-element and checkbox field finders.
spec/​features/​work_packages/​details/​inplace_editor/​subject_editor_spec.rb Standardizes conflict-warning text matching.
spec/​features/​work_packages/​attachments/​attachment_upload_spec.rb Standardizes image-caption text matching.
spec/​features/​wiki/​adding_editing_history_spec.rb Waits for wiki settings before checking menu absence.
spec/​features/​versions/​edit_spec.rb Standardizes version-update text assertions.
spec/​features/​versions/​create_spec.rb Standardizes version-creation text assertions.
spec/​features/​users/​show_spec.rb Adds shared-project setup and confirms profile rendering.
spec/​features/​users/​password_change_spec.rb Standardizes authentication-error text assertions.
spec/​features/​users/​my/​access_tokens_spec.rb Adds page-load checks and standardizes token text assertions.
spec/​features/​users/​my_spec.rb Standardizes account-update text assertions.
spec/​features/​users/​invite_user_modal/​subproject_invite_spec.rb Uses a scoped Invite button action.
spec/​features/​users/​invite_user_modal/​invite_user_modal_spec.rb Uses scoped Invite button actions.
spec/​features/​users/​delete_spec.rb Standardizes text checks and confirms page rendering.
spec/​features/​users/​brute_force_spec.rb Standardizes login-failure text assertions.
spec/​features/​types/​form_configuration_spec.rb Uses negative CSS matchers for unavailable actions.
spec/​features/​types/​form_configuration_query_spec.rb Combines embedded-table selectors.
spec/​features/​statuses/​statuses_administration_spec.rb Standardizes status-list text assertions.
spec/​features/​search/​search_spec.rb Uses waiting URL matchers for search parameters.
spec/​features/​repositories/​create_repository_spec.rb Uses specific field/button matchers and explicit visibility.
spec/​features/​projects/​project_custom_fields/​settings/​mapping_spec.rb Standardizes custom-field text assertions.
spec/​features/​projects/​project_custom_fields/​overview_page/​update_spec.rb Standardizes custom-field value text assertions.
spec/​features/​projects/​project_custom_fields/​overview_page/​dialog/​render_spec.rb Standardizes dialog text matching.
spec/​features/​projects/​persisted_lists_spec.rb Checks the authorization error before list absence.
spec/​features/​projects/​persisted_lists_sharing_spec.rb Standardizes shared-list text matching.
spec/​features/​projects/​navigation_spec.rb Checks the expected path before the excluded path.
spec/​features/​projects/​lists/​table_spec.rb Checks public-project presence before private-project absence.
spec/​features/​projects/​export_spec.rb Standardizes export queue text matching.
spec/​features/​projects/​edit_settings_spec.rb Adds a loaded-field check and standardizes update messages.
spec/​features/​projects/​create_spec.rb Standardizes project-creation text assertions.
spec/​features/​programs/​create_spec.rb Standardizes creation and authorization text assertions.
spec/​features/​portfolios/​index_spec.rb Standardizes authorization-error text matching.
spec/​features/​portfolios/​create_spec.rb Standardizes creation and authorization text assertions.
spec/​features/​placeholder_users/​delete_spec.rb Standardizes permission-error text matching.
spec/​features/​placeholder_users/​create_spec.rb Uses a waiting redirect-path matcher.
spec/​features/​news/​creation_and_commenting_spec.rb Standardizes news and comment text assertions.
spec/​features/​menu_items/​menu_permissions_spec.rb Uses explicit menu visibility options.
spec/​features/​localization_spec.rb Standardizes translated text assertions.
spec/​features/​groups/​group_show_spec.rb Standardizes missing-page text matching.
spec/​features/​global_roles/​global_create_project_spec.rb Checks permission presence before absence.
spec/​features/​forums/​topic_page_spec.rb Uses a waiting URL matcher.
spec/​features/​forums/​attachment_upload_spec.rb Standardizes attachment-caption text assertions.
spec/​features/​external_link_capture_spec.rb Uses waiting redirect URL matchers.
spec/​features/​auth/​omniauth_spec.rb Uses a waiting post-login URL matcher.
spec/​features/​auth/​login_spec.rb Standardizes login-error text matching.
spec/​features/​auth/​auth_stages_spec.rb Uses waiting authentication-stage path matchers.
spec/​features/​auth/​auth_source_sso_logout_spec.rb Uses a waiting logout URL matcher.
spec/​features/​admin/​settings/​work_package_priorities_spec.rb Standardizes priority text assertions.
spec/​features/​admin/​settings_spec.rb Standardizes settings-section text matching.
spec/​features/​admin/​scim_clients/​index_spec.rb Standardizes client-list text assertions.
spec/​features/​admin/​custom_fields/​work_packages/​multi_value_list_spec.rb Uses field matchers for option inputs.
spec/​features/​admin/​backup_spec.rb Standardizes backup status and token text assertions.
spec/​features/​a11y/​work_packages/​work_package_query_spec.rb Waits for the documentation-window URL.
spec/​controllers/​my_controller_spec.rb Standardizes rendered custom-field text matching.
spec/​components/​work_packages/​dialogs/​create_form_component_spec.rb Uses field matchers for subject enabled/disabled states.
spec/​components/​work_package_types/​defaults_component_spec.rb Uses explicit hidden-input visibility.
spec/​components/​projects/​status_button_component_spec.rb Uses a dedicated negative element matcher.
spec/​components/​projects/​row_component_spec.rb Uses a dedicated negative action-menu matcher.
spec/​components/​op_primer/​check_all_component_spec.rb Standardizes separator text matching.
spec/​components/​members/​role_form_component_spec.rb Uses explicit form visibility.
spec/​components/​enterprise_edition/​banner_component_spec.rb Standardizes banner text assertions.
modules/​webhooks/​spec/​components/​webhooks/​outgoing/​webhooks/​row_component_spec.rb Standardizes webhook-row text assertions.
modules/​two_factor_authentication/​spec/​features/​shared_two_factor_examples.rb Uses field matchers for one-time-password inputs.
modules/​two_factor_authentication/​spec/​features/​remember_cookie/​login_with_remember_cookie_spec.rb Uses field presence and absence matchers.
modules/​two_factor_authentication/​spec/​features/​password_change_spec.rb Uses a one-time-password field matcher.
modules/​two_factor_authentication/​spec/​features/​my_two_factor_devices_spec.rb Standardizes field and device-text assertions.
modules/​two_factor_authentication/​spec/​features/​login/​switch_available_devices_spec.rb Uses field matchers when switching devices.
modules/​two_factor_authentication/​spec/​features/​account_activation_spec.rb Standardizes invalid-token text matching.
modules/​team_planner/​spec/​features/​team_planner_spec.rb Standardizes empty-state text matching.
modules/​team_planner/​spec/​features/​team_planner_global_create_spec.rb Standardizes creation-form text matching.
modules/​storages/​spec/​features/​storages/​admin/​project_storages_spec.rb Standardizes visibility and dialog-absence checks.
modules/​storages/​spec/​features/​storages_menu_links_spec.rb Confirms project rendering before checking link absence.
modules/​storages/​spec/​features/​manage_project_storage_spec.rb Adds page-load checks and standardizes option text assertions.
modules/​storages/​spec/​components/​storages/​project_storages/​oauth_access_granted_modal_component_spec.rb Standardizes access-granted modal text assertions.
modules/​storages/​spec/​components/​storages/​admin/​storages/​oauth_access_granted_modal_component_spec.rb Standardizes administrator modal text assertions.
modules/​storages/​spec/​components/​storages/​admin/​storage_audience_info_component_spec.rb Standardizes audience-information text assertions.
modules/​reporting/​spec/​features/​subproject_spec.rb Standardizes report-creation text matching.
modules/​reporting/​spec/​features/​permissions_spec.rb Standardizes permission-dependent report text assertions.
modules/​reporting/​spec/​features/​export_timesheet_spec.rb Standardizes export queue text matching.
modules/​reporting/​spec/​features/​export_cost_report_spec.rb Standardizes export queue text matching.
modules/​reporting/​spec/​features/​date_filter_spec.rb Standardizes date-filter result text assertions.
modules/​overviews/​spec/​features/​project_description_widget_spec.rb Standardizes description-widget text matching.
modules/​overviews/​spec/​features/​managing_dashboard_page_spec.rb Standardizes dashboard and widget-dialog text assertions.
modules/​my_page/​spec/​features/​my/​news_spec.rb Standardizes news-widget text assertions.
modules/​my_page/​spec/​features/​my/​my_page_spec.rb Standardizes work-package widget text assertions.
modules/​my_page/​spec/​features/​my/​documents_spec.rb Standardizes document-widget text assertions.
modules/​my_page/​spec/​features/​my/​assigned_to_me_spec.rb Uses a scoped pagination button action.
modules/​meeting/​spec/​support/​pages/​meetings/​show.rb Uses negative CSS and checkbox field helpers.
modules/​meeting/​spec/​features/​structured_meetings/​structured_meeting_crud_spec.rb Standardizes title-validation text matching.
modules/​meeting/​spec/​features/​structured_meetings/​attachment_upload_spec.rb Standardizes attachment-caption text matching.
modules/​meeting/​spec/​features/​recurring_meetings/​recurring_meeting_create_spec.rb Standardizes text and negative CSS assertions.
modules/​meeting/​spec/​components/​meetings/​email_updates_banner_component_spec.rb Uses negative CSS warning-banner matchers.
modules/​job_status/​spec/​features/​job_status_spec.rb Standardizes job-status error text assertions.
modules/​grids/​spec/​support/​pages/​grid.rb Standardizes widget-dialog text assertions.
modules/​grids/​spec/​components/​grids/​widgets/​news_spec.rb Standardizes news metadata text matching.
modules/​gitlab_integration/​spec/​features/​admin_gitlab_integration_spec.rb Standardizes integration-update text assertions.
modules/​github_integration/​spec/​features/​work_package_github_tab_spec.rb Standardizes empty-tab text assertions.
modules/​github_integration/​spec/​features/​admin_github_integration_spec.rb Standardizes integration settings text assertions.
modules/​gantt/​spec/​features/​timeline/​timeline_navigation_spec.rb Scopes group-expander actions with within.
modules/​documents/​spec/​features/​real_time_collaboration_spec.rb Standardizes collaborator and editor text assertions.
modules/​documents/​spec/​features/​external_links_in_block_note_spec.rb Uses a waiting external-redirect URL matcher.
modules/​documents/​spec/​features/​documents/​project/​show_edit_document_spec.rb Standardizes document-editing text assertions.
modules/​documents/​spec/​features/​documents/​project/​delete_document_spec.rb Standardizes deletion-error text assertions.
modules/​documents/​spec/​features/​documents/​project/​create_document_spec.rb Standardizes creation and validation text assertions.
modules/​documents/​spec/​features/​documents/​admin/​settings/​document_collaboration_settings_spec.rb Standardizes collaboration-settings text assertions.
modules/​documents/​spec/​features/​document_categories_spec.rb Standardizes migration-notice and authorization text assertions.
modules/​documents/​spec/​features/​block_note_editor_spec.rb Standardizes editor visibility and text assertions.
modules/​documents/​spec/​features/​attachment_upload_spec.rb Standardizes text and negative element assertions.
modules/​costs/​spec/​features/​time_entry/​activity_spec.rb Standardizes activity text assertions.
modules/​calendar/​spec/​features/​calendars_global_create_spec.rb Standardizes creation-form text matching.
modules/​calendar/​spec/​features/​calendar_sharing_spec.rb Standardizes validation and update text assertions.
modules/​budgets/​spec/​support/​pages/​index_budget.rb Standardizes budget-absence text matching.
modules/​budgets/​spec/​support/​pages/​destroy_info.rb Standardizes deletion-page text matching.
modules/​budgets/​spec/​features/​budgets/​update_budget_spec.rb Standardizes budget-update and cost text assertions.
modules/​budgets/​spec/​features/​budgets/​attachment_upload_spec.rb Standardizes attachment-caption text assertions.
modules/​boards/​spec/​features/​support/​board_page.rb Uses negative CSS loading checks and named menu buttons.
modules/​boards/​spec/​features/​support/​board_list_page.rb Standardizes empty-board-list text matching.
modules/​boards/​spec/​features/​menu_items/​top_menu_item_spec.rb Standardizes menu text and visibility options.
modules/​boards/​spec/​features/​menu_items/​global_menu_item_spec.rb Standardizes global-menu text assertions.
modules/​boards/​spec/​features/​boards_global_create_spec.rb Standardizes creation-form text matching.
modules/​boards/​spec/​features/​board_enterprise_spec.rb Standardizes board-name text assertions.
modules/​boards/​spec/​features/​action_boards/​version_board_spec.rb Standardizes version text assertions.
modules/​boards/​spec/​features/​action_boards/​subproject_board_spec.rb Standardizes excluded-work-package text matching.
modules/​bim/​spec/​support/​pages/​ifc_models/​index.rb Uses negative CSS permission matchers.
modules/​bim/​spec/​features/​ifc_models/​regular_ifc_upload_spec.rb Standardizes upload-error text matching.
modules/​bim/​spec/​features/​bcf/​export_spec.rb Standardizes export queue text matching.
modules/​bim/​spec/​features/​bcf/​api_authorization_spec.rb Standardizes API response text assertions.
modules/​backlogs/​spec/​support/​pages/​backlog.rb Uses explicit menu-overlay visibility options.
modules/​auth_saml/​spec/​requests/​saml_metadata_refresh_spec.rb Finds the metadata token explicitly as a hidden field.

Review effort: Balanced

myabc added 2 commits November 2, 2026 15:12
Fixes RuboCop Capybara offenses whose fix changes when an expectation
is evaluated:

- Capybara/FindAllFirst: `all(...)[0]` becomes `first(...)`, which
  waits for a match and raises instead of returning nil.
- Capybara/RSpec/CurrentUrlExpectation, CurrentPathExpectation:
  expectations on `current_url` and `current_path` become
  `have_current_path`, which retries until the navigation completes
  instead of reading the URL once.
- Capybara/RSpec/NegationMatcherAfterVisit: a negative expectation
  straight after `visit` passes before the page has rendered. Each
  such example now asserts something present on the page first,
  reordering existing assertions where the example already had one.

The user profile spec for another user only passed because that user
could not see the profile at all and got a 404. It now shares a
project with the profile owner, so the profile renders and the
assertion that the group stays hidden is meaningful again.

The backup token reset spec waited for the dialog heading with an
expectation in a before hook. That expectation is dropped; checking the
confirmation checkbox already waits for the dialog to open.
Fixes the RuboCop Capybara offenses that swap a generic CSS query for
a selector-specific one:

- Capybara/SpecificFinders: `find("input[...]")` becomes
  `find_field`. `type: "hidden"` is passed where the input is hidden,
  as `find_field` skips hidden inputs otherwise.
- Capybara/SpecificActions: `find("... button", text:).click`
  becomes `click_button` on the container. Unlike `find`,
  `click_button` ignores disabled buttons.
- Capybara/RSpec/SpecificMatcher: `have_css` on form elements and
  links becomes `have_field`, `have_button`, `have_select` or
  `have_link`. Assertions on a disabled field use
  `have_field(disabled:)`, as `find_field` does not match disabled
  fields by default.
- Capybara/ChainedFind: chained finds are combined into one selector.
  Where the parent filters on `text:`, which CSS cannot express, the
  toast close button is clicked by its title and the remaining
  chains use `within`.
@myabc
myabc force-pushed the housekeeping/rubocop-capybara-fixes branch from 464aaf7 to f47dfb8 Compare November 2, 2026 15:20
@myabc
myabc requested a review from toy November 2, 2026 16:26

This branch has not been deployed

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

Labels

ai: Collaborative 💻 AI generated a substantial part of the code; A human reviewed and understands every line. needs review rubocop 👮 Just rubocop fixes

Development

Successfully merging this pull request may close these issues.

2 participants