From 9db73c5c4ac22a6399c6d37044d9de8c6c7eaa3f Mon Sep 17 00:00:00 2001 From: Sean Doyle Date: Fri, 19 Aug 2022 16:51:28 -0400 Subject: [PATCH] Support `[role="status"]` Add a `:status` selector in the same style as the `:alert` selector. Additionally, extend both the `:alert` and `:status` selectors to accept text as a locator argument. --- README.md | 18 +++++++++++-- .../rspec/matchers.rb | 2 +- .../selectors.rb | 1 + .../selectors/alert.rb | 4 +-- .../selectors/status.rb | 7 +++++ spec/fixtures/status.html | 9 +++++++ spec/matchers/have_alert_spec.rb | 12 +++++++-- spec/matchers/have_status_spec.rb | 17 ++++++++++++ spec/selectors/alert_spec.rb | 12 ++++++++- spec/selectors/status_spec.rb | 27 +++++++++++++++++++ 10 files changed, 101 insertions(+), 8 deletions(-) create mode 100644 lib/capybara_accessible_selectors/selectors/status.rb create mode 100644 spec/fixtures/status.html create mode 100644 spec/matchers/have_status_spec.rb create mode 100644 spec/selectors/status_spec.rb diff --git a/README.md b/README.md index 5010f71..11e1cca 100644 --- a/README.md +++ b/README.md @@ -208,7 +208,7 @@ Selects an element with the role of [`alert`](https://www.w3.org/WAI/ARIA/apg/pa ```ruby expect(page).to have_selector :alert, text: "Successfully saved" -expect(page).to have_alert, text: "Successfully saved" +expect(page).to have_alert text: "Successfully saved" ``` Also see [↓ Expectation shortcuts](#expectation-shortcuts) @@ -474,6 +474,19 @@ Also see - [↓ Expectation shortcuts](#expectation-shortcuts) - [↓ `within_section`](#within_sectionname-find_options-block) +#### `status` + +Selects an element with the role of [`status`](https://www.w3.org/TR/wai-aria-practices-1.1/#status). + +```html +
Important message
+``` + +```ruby +expect(page).to have_selector :status, text: "Successfully saved" +expect(page).to have_status text: "Successfully saved" +``` + #### `tab_panel` Finds a [tab panel](https://www.w3.org/WAI/ARIA/apg/patterns/tabpanel/). @@ -679,6 +692,7 @@ The following expectation shortcuts are also added for both `have_selector_` and - `have_navigation` - `have_region` - `have_section` +- `have_status` - `have_tab_panel` - `have_tab_button` @@ -686,7 +700,7 @@ For example the following two are equivalent: ```ruby expect(page).to have_selector :combo_box, "Foo" -expect(page).to have_combo_box, "Foo" +expect(page).to have_combo_box "Foo" ``` diff --git a/lib/capybara_accessible_selectors/rspec/matchers.rb b/lib/capybara_accessible_selectors/rspec/matchers.rb index 6aec35e..d8feb8e 100644 --- a/lib/capybara_accessible_selectors/rspec/matchers.rb +++ b/lib/capybara_accessible_selectors/rspec/matchers.rb @@ -7,7 +7,7 @@ module Capybara module RSpecMatchers %i[alert banner combo_box contentinfo main menu menuitem modal navigation region - tab_panel tab_button disclosure disclosure_button section item].each do |selector| + tab_panel tab_button disclosure disclosure_button section status item].each do |selector| define_method "have_#{selector}" do |locator = nil, **options, &optional_filter_block| Matchers::HaveSelector.new(selector, locator, **options, &optional_filter_block) end diff --git a/lib/capybara_accessible_selectors/selectors.rb b/lib/capybara_accessible_selectors/selectors.rb index 3e9d6eb..b72ef4f 100644 --- a/lib/capybara_accessible_selectors/selectors.rb +++ b/lib/capybara_accessible_selectors/selectors.rb @@ -13,4 +13,5 @@ require "capybara_accessible_selectors/selectors/region" require "capybara_accessible_selectors/selectors/rich_text" require "capybara_accessible_selectors/selectors/section" +require "capybara_accessible_selectors/selectors/status" require "capybara_accessible_selectors/selectors/tab" diff --git a/lib/capybara_accessible_selectors/selectors/alert.rb b/lib/capybara_accessible_selectors/selectors/alert.rb index ea9cc71..ad92b83 100644 --- a/lib/capybara_accessible_selectors/selectors/alert.rb +++ b/lib/capybara_accessible_selectors/selectors/alert.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true Capybara.add_selector(:alert) do - xpath do |*| - XPath.descendant[XPath.attr(:role) == "alert"] + xpath do |locator, *| + XPath.descendant[XPath.attr(:role) == "alert"][XPath.string.n.is(locator.to_s)] end end diff --git a/lib/capybara_accessible_selectors/selectors/status.rb b/lib/capybara_accessible_selectors/selectors/status.rb new file mode 100644 index 0000000..f3c6c5e --- /dev/null +++ b/lib/capybara_accessible_selectors/selectors/status.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +Capybara.add_selector(:status) do + xpath do |locator, *| + XPath.descendant[XPath.attr(:role) == "status"][XPath.string.is(locator.to_s)] + end +end diff --git a/spec/fixtures/status.html b/spec/fixtures/status.html new file mode 100644 index 0000000..94693ba --- /dev/null +++ b/spec/fixtures/status.html @@ -0,0 +1,9 @@ + + +
+ Status message +
+ +
+ Just a message +
diff --git a/spec/matchers/have_alert_spec.rb b/spec/matchers/have_alert_spec.rb index a51d0f7..b6c31b4 100644 --- a/spec/matchers/have_alert_spec.rb +++ b/spec/matchers/have_alert_spec.rb @@ -5,11 +5,19 @@ visit "/alert.html" end - it "matches using a custom matcher" do + it "matches using a custom matcher with locator" do + expect(page).to have_alert("Alert") + end + + it "matches using a custom matcher with text: filter" do expect(page).to have_alert(text: "Alert") end - it "matches using a negated custom matcher" do + it "matches using a negated custom matcher with locator" do + expect(page).to have_no_alert("foo") + end + + it "matches using a negated custom matcher with text: filter" do expect(page).to have_no_alert(text: "foo") end end diff --git a/spec/matchers/have_status_spec.rb b/spec/matchers/have_status_spec.rb new file mode 100644 index 0000000..7f63573 --- /dev/null +++ b/spec/matchers/have_status_spec.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +describe "have_status" do + before do + visit "/status.html" + end + + it "matches using a custom matcher" do + expect(page).to have_status("Status") + expect(page).to have_status(text: "Status") + end + + it "matches using a negated custom matcher" do + expect(page).to have_no_status("foo") + expect(page).to have_no_status(text: "foo") + end +end diff --git a/spec/selectors/alert_spec.rb b/spec/selectors/alert_spec.rb index 540ff13..dbed7d3 100644 --- a/spec/selectors/alert_spec.rb +++ b/spec/selectors/alert_spec.rb @@ -5,7 +5,17 @@ visit "/alert.html" end - it "finds alerts" do + it "finds alerts without arguments" do + alert = page.find(:css, "[role=alert]") + expect(page.find(:alert)).to eq alert + end + + it "finds alerts with a locator" do + alert = page.find(:css, "[role=alert]") + expect(page.find(:alert, "Alert message")).to eq alert + end + + it "finds alerts with a text: filter" do alert = page.find(:css, "[role=alert]") expect(page.find(:alert, text: "Alert message")).to eq alert end diff --git a/spec/selectors/status_spec.rb b/spec/selectors/status_spec.rb new file mode 100644 index 0000000..f773985 --- /dev/null +++ b/spec/selectors/status_spec.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +describe "status selector" do + before do + visit "/status.html" + end + + it "finds statuses without arguments" do + status = page.find(:css, "[role=status]") + expect(page.find(:status)).to eq status + end + + it "finds statuses with a locator" do + status = page.find(:css, "[role=status]") + expect(page.find(:status, "Status message")).to eq status + end + + it "finds statuses with a text: filter" do + status = page.find(:css, "[role=status]") + expect(page.find(:status, text: "Status message")).to eq status + end + + it "matches selector" do + status = page.find(:css, "[role=status]") + expect(status).to match_selector :status + end +end