Alexiel
Alexiel

Reputation: 45

Can't access an element by a data- attribute with an underscore

Good day everyone!

I have an element

<tbody class="cp-ads-list__table-item _sas-offers-table__item cp-ads-list__table- item_state-deposit" data-card_id="16676514">

I'd like to access it by the data-card_id tag, but when I try the following

@browser.tbody(:data_card_id => "16676514").hover

I get an error

unable to locate element, using {:data_card_id=>"16676514", :tag_name=>"tbody"} (Watir::Exception::UnknownObjectException)

I guess my code would have worked if the tag were "data-card-id", but it's "data-card_id". How do I access my element by this attribute?

Upvotes: 3

Views: 560

Answers (1)

Justin Ko
Justin Ko

Reputation: 46836

Problem

You are right that the problem is the underscore in the data attribute. As seen in the ElementLocator, when building the XPath expression, all underscores are converted to dashes (in the else part of the statement):

def lhs_for(key)
  case key
  when :text, 'text'
    'normalize-space()'
  when :href
    # TODO: change this behaviour?
    'normalize-space(@href)'
  when :type
    # type attributes can be upper case - downcase them
    # https://github.com/watir/watir-webdriver/issues/72
    XpathSupport.downcase('@type')
  else
    "@#{key.to_s.gsub("_", "-")}"
  end
end

Solution - One-Off

If this is the only data attribute that is using underscores (rather than dashes), I would probably manually build the XPath or CSS expression.

@browser.tbody(:css => '[data-card_id="16676514"]').hover

Solution - Monkey Patch

If using underscores is a standard on the website, I would probably consider monkey patching the lhs_for method. You could monkey patch the method so that you only change the first underscore for data attributes:

module Watir
  class ElementLocator
    def lhs_for(key)
      puts 'hi'
      case key
      when :text, 'text'
        'normalize-space()'
      when :href
        # TODO: change this behaviour?
        'normalize-space(@href)'
      when :type
        # type attributes can be upper case - downcase them
        # https://github.com/watir/watir-webdriver/issues/72
        XpathSupport.downcase('@type')
      else
        if key.to_s.start_with?('data')
          "@#{key.to_s.sub("_", "-")}"
        else
          "@#{key.to_s.gsub("_", "-")}"
        end
      end
    end
  end
end

This would then allow your original code to work:

@browser.tbody(:data_card_id => "16676514").hover

Upvotes: 4

Related Questions