Use Capybara methods to find/click/check links

We applied the Capybara/SpecificMatcher in commit f52a86b46.  However,
this rule doesn't convert methods finding <a> tags to methods finding
links because <a> tags only count as links when they've got the `href`
attribute. For instance, in the `xss_spec.rb` file we check what happens
when clicking on an anchor tag because we're testing that the `href`
attribute has been removed and so we can't use `click_link`.

So, basically, we can't enable a rule to automatically detect when we're
using `have_css` instead of `have_link`, but we should still do it
because `have_link` adds an extra check which affects accessibility
since it makes sure the tag has the `href` attribute and so it's
recognizable as a link by screen readers.
This commit is contained in:
Javi Martín
2023-09-10 22:19:01 +02:00
parent 614b4fbe4c
commit ea913f9332
15 changed files with 42 additions and 41 deletions

View File

@@ -5,13 +5,13 @@ describe Admin::ActionComponent do
it "includes an HTML class for the action by default" do it "includes an HTML class for the action by default" do
render_inline Admin::ActionComponent.new(:edit, double, path: "/") render_inline Admin::ActionComponent.new(:edit, double, path: "/")
expect(page).to have_css "a.edit-link.admin-action" expect(page).to have_link class: %w[edit-link admin-action]
end end
it "keeps the admin-action class when the class is overwritten" do it "keeps the admin-action class when the class is overwritten" do
render_inline Admin::ActionComponent.new(:edit, double, path: "/", class: "modify-link") render_inline Admin::ActionComponent.new(:edit, double, path: "/", class: "modify-link")
expect(page).to have_css "a.modify-link.admin-action" expect(page).to have_link class: %w[modify-link admin-action]
expect(page).not_to have_css ".edit-link" expect(page).not_to have_css ".edit-link"
end end
end end
@@ -28,7 +28,7 @@ describe Admin::ActionComponent do
render_inline Admin::ActionComponent.new(:edit, record, path: "/") render_inline Admin::ActionComponent.new(:edit, record, path: "/")
expect(page).to have_css "a.edit-link#edit_computer_1" expect(page).to have_link class: "edit-link", id: "edit_computer_1"
end end
it "can be overwritten" do it "can be overwritten" do
@@ -36,7 +36,7 @@ describe Admin::ActionComponent do
render_inline Admin::ActionComponent.new(:edit, record, path: "/", id: "my_id") render_inline Admin::ActionComponent.new(:edit, record, path: "/", id: "my_id")
expect(page).to have_css "a.edit-link#my_id" expect(page).to have_link class: "edit-link", id: "my_id"
expect(page).not_to have_css "#edit_computer_1" expect(page).not_to have_css "#edit_computer_1"
end end
end end

View File

@@ -7,7 +7,7 @@ describe Admin::TableActionsComponent, :admin do
render_inline Admin::TableActionsComponent.new(record) render_inline Admin::TableActionsComponent.new(record)
expect(page).to have_link count: 1 expect(page).to have_link count: 1
expect(page).to have_css "a[href*='edit']", exact_text: "Edit" expect(page).to have_link "Edit", href: /edit/
expect(page).to have_css "a[aria-label='Edit Important!']" expect(page).to have_css "a[aria-label='Edit Important!']"
expect(page).to have_button count: 1 expect(page).to have_button count: 1
@@ -56,7 +56,7 @@ describe Admin::TableActionsComponent, :admin do
it "allows custom options" do it "allows custom options" do
render_inline Admin::TableActionsComponent.new(record, edit_options: { id: "edit_me" }) render_inline Admin::TableActionsComponent.new(record, edit_options: { id: "edit_me" })
expect(page).to have_css "a#edit_me" expect(page).to have_link id: "edit_me"
end end
it "allows custom content" do it "allows custom content" do
@@ -64,7 +64,7 @@ describe Admin::TableActionsComponent, :admin do
"<a href='/'>Main</a>".html_safe "<a href='/'>Main</a>".html_safe
end end
expect(page).to have_css "a", count: 2 expect(page).to have_link count: 2
expect(page).to have_link "Main", href: "/" expect(page).to have_link "Main", href: "/"
expect(page).to have_link "Edit" expect(page).to have_link "Edit"
@@ -77,7 +77,7 @@ describe Admin::TableActionsComponent, :admin do
render_inline Admin::TableActionsComponent.new(create(:sdg_local_target)) render_inline Admin::TableActionsComponent.new(create(:sdg_local_target))
expect(page).to have_link count: 1 expect(page).to have_link count: 1
expect(page).to have_css "a[href^='/sdg_management/'][href*='edit']", exact_text: "Edit" expect(page).to have_link "Edit", href: /\A\/sdg_management\/(.+)edit/
expect(page).to have_button count: 1 expect(page).to have_button count: 1
expect(page).to have_css "form[action^='/sdg_management/']", exact_text: "Delete" expect(page).to have_css "form[action^='/sdg_management/']", exact_text: "Delete"

View File

@@ -11,7 +11,6 @@ describe Budgets::PhasesComponent do
budget.current_phase.update!(main_link_text: "Phase link!", main_link_url: "https://consuldemocracy.org") budget.current_phase.update!(main_link_text: "Phase link!", main_link_url: "https://consuldemocracy.org")
render_inline Budgets::PhasesComponent.new(budget) render_inline Budgets::PhasesComponent.new(budget)
expect(page).to have_css(".main-link") expect(page).to have_link "Phase link!", href: "https://consuldemocracy.org", class: "main-link"
expect(page).to have_link("Phase link!", href: "https://consuldemocracy.org")
end end
end end

View File

@@ -39,7 +39,7 @@ describe SDGManagement::MenuComponent do
it "does not generate links to any processes" do it "does not generate links to any processes" do
render_inline component render_inline component
expect(page).to have_css "a", count: 2 expect(page).to have_link count: 2
expect(page).to have_link "Goals and Targets" expect(page).to have_link "Goals and Targets"
expect(page).to have_link "SDG homepage" expect(page).to have_link "SDG homepage"
end end
@@ -57,7 +57,7 @@ describe SDGManagement::MenuComponent do
it "does not generate links to any processes" do it "does not generate links to any processes" do
render_inline component render_inline component
expect(page).to have_css "a", count: 2 expect(page).to have_link count: 2
expect(page).to have_link "Goals and Targets" expect(page).to have_link "Goals and Targets"
expect(page).to have_link "SDG homepage" expect(page).to have_link "SDG homepage"
end end

View File

@@ -44,9 +44,9 @@ describe Shared::LinkListComponent do
["Home", "/", class: "root"], ["Info", "/info", id: "info"] ["Home", "/", class: "root"], ["Info", "/info", id: "info"]
) )
expect(page).to have_css "a", count: 2 expect(page).to have_link count: 2
expect(page).to have_css "a.root", count: 1, exact_text: "Home" expect(page).to have_link "Home", class: "root", count: 1
expect(page).to have_css "a#info", count: 1, exact_text: "Info" expect(page).to have_link "Info", id: "info", count: 1
end end
it "ignores nil entries" do it "ignores nil entries" do
@@ -55,8 +55,8 @@ describe Shared::LinkListComponent do
) )
expect(page).to have_css "li", count: 2 expect(page).to have_css "li", count: 2
expect(page).to have_css "a.root", count: 1, exact_text: "Home" expect(page).to have_link "Home", class: "root", count: 1
expect(page).to have_css "a#info", count: 1, exact_text: "Info" expect(page).to have_link "Info", id: "info", count: 1
end end
it "ignores empty entries" do it "ignores empty entries" do
@@ -65,8 +65,8 @@ describe Shared::LinkListComponent do
) )
expect(page).to have_css "li", count: 2 expect(page).to have_css "li", count: 2
expect(page).to have_css "a.root", count: 1, exact_text: "Home" expect(page).to have_link "Home", class: "root", count: 1
expect(page).to have_css "a#info", count: 1, exact_text: "Info" expect(page).to have_link "Info", id: "info", count: 1
end end
it "accepts an optional condition to check the active element" do it "accepts an optional condition to check the active element" do
@@ -90,8 +90,8 @@ describe Shared::LinkListComponent do
expect(page).to have_css "li", count: 3 expect(page).to have_css "li", count: 3
expect(page).to have_css "li[aria-current='true']", count: 1, exact_text: "Info" expect(page).to have_css "li[aria-current='true']", count: 1, exact_text: "Info"
expect(page).to have_css "a.root", count: 1, exact_text: "Home" expect(page).to have_link "Home", class: "root", count: 1
expect(page).to have_css "a#info", count: 1, exact_text: "Info" expect(page).to have_link "Info", id: "info", count: 1
expect(page).to have_css "a[rel='help']", count: 1, exact_text: "Help" expect(page).to have_css "a[rel='help']", count: 1, exact_text: "Help"
end end
end end

View File

@@ -25,7 +25,7 @@ shared_examples "nested documentable" do |login_as_name, documentable_factory_na
do_login_for user_to_login, management: management do_login_for user_to_login, management: management
visit send(path, arguments) visit send(path, arguments)
expect(page).to have_css "#new_document_link" expect(page).to have_link id: "new_document_link"
end end
scenario "Should not show new document link when scenario "Should not show new document link when
@@ -219,7 +219,7 @@ shared_examples "nested documentable" do |login_as_name, documentable_factory_na
# Review # Review
# Doble check why the file is stored with a name different to empty.pdf # Doble check why the file is stored with a name different to empty.pdf
expect(page).to have_css("a[href$='.pdf']") expect(page).to have_link href: /.pdf\Z/
end end
scenario "Should show resource with new document after successful creation with scenario "Should show resource with new document after successful creation with
@@ -269,7 +269,7 @@ shared_examples "nested documentable" do |login_as_name, documentable_factory_na
click_on "Remove document" click_on "Remove document"
end end
expect(page).to have_css "#new_document_link" expect(page).to have_link id: "new_document_link"
end end
scenario "Should remove nested field after remove document" do scenario "Should remove nested field after remove document" do

View File

@@ -228,7 +228,7 @@ shared_examples "nested imageable" do |imageable_factory_name, path, imageable_p
click_link "Remove image" click_link "Remove image"
expect(page).not_to have_css ".image" expect(page).not_to have_css ".image"
expect(page).to have_css "a#new_image_link" expect(page).to have_link id: "new_image_link"
end end
scenario "don't duplicate fields after removing and adding an image" do scenario "don't duplicate fields after removing and adding an image" do

View File

@@ -55,8 +55,10 @@ describe "Admin custom information texts", :admin do
visit admin_site_customization_information_texts_path visit admin_site_customization_information_texts_path
within("#information-texts-tabs") { click_link "Proposals" } within("#information-texts-tabs") { click_link "Proposals" }
expect(find("a[href=\"/admin/site_customization/information_texts?tab=proposals\"].is-active"))
.to have_content "Proposals" expect(page).to have_link "Proposals",
href: "/admin/site_customization/information_texts?tab=proposals",
class: "is-active"
end end
context "Globalization" do context "Globalization" do

View File

@@ -155,7 +155,7 @@ describe "Polls" do
within ".js-questions" do within ".js-questions" do
expect(page).to have_css ".nested-fields", count: 2 expect(page).to have_css ".nested-fields", count: 2
within first(".nested-fields") do within first(".nested-fields") do
find("a.delete").click click_link class: "delete"
end end
expect(page).to have_css ".nested-fields", count: 1 expect(page).to have_css ".nested-fields", count: 1
end end
@@ -177,7 +177,7 @@ describe "Polls" do
within ".js-questions .js-answers" do within ".js-questions .js-answers" do
expect(page).to have_css ".nested-fields", count: 2 expect(page).to have_css ".nested-fields", count: 2
within first(".nested-fields") do within first(".nested-fields") do
find("a.delete").click click_link class: "delete"
end end
expect(page).to have_css ".nested-fields", count: 1 expect(page).to have_css ".nested-fields", count: 1
end end

View File

@@ -19,7 +19,7 @@ describe "Debates" do
within("#debates") do within("#debates") do
expect(page).to have_content debate.title expect(page).to have_content debate.title
expect(page).to have_content debate.description expect(page).to have_content debate.description
expect(page).to have_css("a[href='#{debate_path(debate)}']", text: debate.title) expect(page).to have_link debate.title, href: debate_path(debate)
end end
end end
end end

View File

@@ -110,7 +110,7 @@ describe "Proposals" do
expect(page).to have_content(proposal1.title) expect(page).to have_content(proposal1.title)
expect(page).to have_content(proposal1.summary) expect(page).to have_content(proposal1.summary)
expect(page).not_to have_content(proposal2.title) expect(page).not_to have_content(proposal2.title)
expect(page).to have_css("a[href='#{management_proposal_path(proposal1)}']", text: proposal1.title) expect(page).to have_link proposal1.title, href: management_proposal_path(proposal1)
end end
end end
@@ -133,9 +133,9 @@ describe "Proposals" do
within(".proposals-list") do within(".proposals-list") do
expect(page).to have_css(".proposal", count: 2) expect(page).to have_css(".proposal", count: 2)
expect(page).to have_css("a[href='#{management_proposal_path(proposal1)}']", text: proposal1.title) expect(page).to have_link proposal1.title, href: management_proposal_path(proposal1)
expect(page).to have_content(proposal1.summary) expect(page).to have_content(proposal1.summary)
expect(page).to have_css("a[href='#{management_proposal_path(proposal2)}']", text: proposal2.title) expect(page).to have_link proposal2.title, href: management_proposal_path(proposal2)
expect(page).to have_content(proposal2.summary) expect(page).to have_content(proposal2.summary)
end end
end end

View File

@@ -27,7 +27,7 @@ describe "Proposals" do
featured_proposals.each do |featured_proposal| featured_proposals.each do |featured_proposal|
within("#featured-proposals") do within("#featured-proposals") do
expect(page).to have_content featured_proposal.title expect(page).to have_content featured_proposal.title
expect(page).to have_css("a[href='#{proposal_path(featured_proposal)}']") expect(page).to have_link href: proposal_path(featured_proposal)
end end
end end
@@ -36,7 +36,7 @@ describe "Proposals" do
within("#proposals") do within("#proposals") do
expect(page).to have_content proposal.title expect(page).to have_content proposal.title
expect(page).to have_content proposal.summary expect(page).to have_content proposal.summary
expect(page).to have_css("a[href='#{proposal_path(proposal)}']", text: proposal.title) expect(page).to have_link proposal.title, href: proposal_path(proposal)
end end
end end
end end

View File

@@ -130,8 +130,8 @@ describe "Tags" do
expect(page).to have_content "Debate updated successfully." expect(page).to have_content "Debate updated successfully."
within(".tags") do within(".tags") do
expect(page).to have_css("a", text: "Economía") expect(page).to have_link "Economía"
expect(page).to have_css("a", text: "Hacienda") expect(page).to have_link "Hacienda"
end end
end end

View File

@@ -166,8 +166,8 @@ describe "Tags" do
expect(page).to have_content "Proposal updated successfully." expect(page).to have_content "Proposal updated successfully."
within(".tags") do within(".tags") do
expect(page).to have_css("a", text: "Economía") expect(page).to have_link "Economía"
expect(page).to have_css("a", text: "Hacienda") expect(page).to have_link "Hacienda"
end end
end end

View File

@@ -102,8 +102,8 @@ describe "Tags" do
expect(page).to have_content "Debate updated successfully." expect(page).to have_content "Debate updated successfully."
within(".tags") do within(".tags") do
expect(page).to have_css("a", text: "Economía") expect(page).to have_link "Economía"
expect(page).to have_css("a", text: "Hacienda") expect(page).to have_link "Hacienda"
end end
end end