Read more

An auto-mapper for ARIA labels and BEM classes in Cucumber selectors

Henning Koch
September 01, 2015Software engineer at makandra GmbH

Spreewald Show archive.org snapshot comes with a selector_for helper that matches an English term like the user's profile into a CSS selector. This is useful for steps that refer to a particular section of the page, like the following:

Then I should see "Bruce" within the user's profile
                                 ^^^^^^^^^^^^^^^^^^
Illustration UI/UX Design

UI/UX Design by makandra brand

We make sure that your target audience has the best possible experience with your digital product. You get:

  • Design tailored to your audience
  • Proven processes customized to your needs
  • An expert team of experienced designers
Read more Show archive.org snapshot

If you're too lazy to manually translate English to a CSS selector by adding a line to features/env/selectors.rb, we already have an auto-mapper to translate English into BEM classes.

This card expands on the idea by also allowing to refer to an element by its aria-label Show archive.org snapshot attribute. aria-label is usually employed to assist users with disabilities. It is also very practical to label things for integration tests.

With the auto-mapper below you can write this:

Then I should see "Bruce" within the user's profile

... and it will match either this:

<div aria-label="user's profile">
  Bruce Wayne
</div>

... or this:

<div class="user--profile">
  Bruce Wayne
</div>

Code

Save this to features/support/selectors.rb, or update your file:

module HtmlSelectorsHelpers
  def selector_for(locator)
    case locator

    # Auto-mapper for BEM classes and ARIA labels
    #
    # Usage examples:
    #   the main menu -> '.main-menu, [aria-label="main menu"]'
    #   the item box's header -> '.item-box--header, [aria-label="item box's header"]'
    #   the slider's item that is current -> '.slider--item.is-current, [aria-label="slider's item that is current"]'
    when /^the (.*)$/

      match = $1
      match =~ /^(.+?)(?:'s (.+?))?(?: that (.+))?$/

      bem_selector = '.'
      bem_selector << selectorify($1)
      bem_selector << '--' << selectorify($2) if $2
      bem_selector << '.' << selectorify($3) if $3
      bem_selector

      aria_selector = '[aria-label="'
      aria_selector << match.gsub('"', '\\"')
      aria_selector << '"]'

      [bem_selector, aria_selector].join(', ')

    when /^"(.+)"$/
      $1

    else
      raise "Can't find mapping from \"#{locator}\" to a selector.\n" +
              "Now, go and add a mapping in #{__FILE__}"
    end
  end

  private

  def selectorify(string)
    string.gsub(/ /, '-')
  end

end

World(HtmlSelectorsHelpers)
Henning Koch
September 01, 2015Software engineer at makandra GmbH
Posted by Henning Koch to makandra dev (2015-09-01 13:08)