0
votes

I've been reading different answers for hours but couldn't find a solution for testing using select2 and Capybara (Webkit driver).

I want to select an option from the select2 and, after that, check if some element value has changed (selecting and option fires an event to add a fee to a number that is in the view also). The problem is that I don't know how to select the element in order to fire the js event, because doing something like this works for the select but doesn't fire the js event:

select('VISA 4242 2020/10').select_option

(I've set the Capybara driver to use Webkit Javascript Driver)

This is the html before clicking on the select input (container is closed):

<fieldset class="form-group">
  <label for="source_id">Payment Method</label>
  <select name="source_id" id="js-payment-method" required="required" autofocus="autofocus" class="form-control normal-select2 select2-hidden-accessible" tabindex="-1" aria-hidden="true">
    <option value="">Select a payment method</option>
    <option value="ba_1">TEST BANK 6789 </option>
    <option value="card_1">VISA 4242 2021/4</option>
    <option value="ba_2">TEST BANK 1116 </option>
  </select>
  <span class="select2 select2-container select2-container--default select2-container--below" dir="ltr" style="width: 100px;">
    <span class="selection">
      <span class="select2-selection select2-selection--single" role="combobox" aria-haspopup="true" aria-expanded="false" tabindex="0" aria-labelledby="select2-js-payment-method-container">
        <span class="select2-selection__rendered" id="select2-js-payment-method-container" title="VISA 4242 2021/4">
          <span class="select2-selection__placeholder">Search...</span>
        </span>
        <span class="select2-selection__arrow" role="presentation">
          <b role="presentation"></b>
        </span>
      </span>
   </span>
   <span class="dropdown-wrapper" aria-hidden="true"></span>
  </span>
</fieldset>

This is the html after clicking on the select input (container is opened):

<fieldset class="form-group">
  <label for="source_id">Payment Method</label>
  <select name="source_id" id="js-payment-method" required="required" autofocus="autofocus" class="form-control normal-select2 select2-hidden-accessible" tabindex="-1" aria-hidden="true">
    <option value="">Select a payment method</option>
    <option value="ba_1">TEST BANK 6789 </option>
    <option value="card_1">VISA 4242 2021/4</option>
    <option value="ba_2">TEST BANK 1116 </option>
  </select>
  <span class="select2 select2-container select2-container--default select2-container--below select2-container--open" dir="ltr" style="width: 100px;">
    <span class="selection">
      <span class="select2-selection select2-selection--single" role="combobox" aria-haspopup="true" aria-expanded="true" tabindex="0" aria-labelledby="select2-js-payment-method-container" aria-owns="select2-js-payment-method-results" aria-activedescendant="select2-js-payment-method-result-1rcw-card_1">
        <span class="select2-selection__rendered" id="select2-js-payment-method-container" title="TEST BANK 6789 ">
          <span class="select2-selection__placeholder">Search...</span>
        </span>
        <span class="select2-selection__arrow" role="presentation">
          <b role="presentation"></b>
        </span>
      </span>
    </span>
    <span class="dropdown-wrapper" aria-hidden="true"></span>
  </span>
</fieldset>

Thanks a lot!

1

1 Answers

1
votes

The code select('VISA 4242 2020/10').select_option makes no sense in Capybara. select('VISA 4242 2020/10') would select the option element containing the text 'VISA 4242 2020/10' and return that option element, which you then call select_option on again. So it would just attempt to select the same option twice. If you were dealing with a normal HTML select it would make more sense to call select('VISA 4242 2020/10', from: 'js-payment-method'). That would find the relevant <option> inside the <select> element with the id of 'js-payment-method' and then select it (see more about this at the bottom of this answer).

That being said, you're not dealing with a normal HTML <select> element, you're dealing with a JS widget which is replacing that select. If you inspect the page while in a browser you'll see that the actual <select> element is non-visible, and hence you can't use the select method. The rule when dealing with JS widgets is to do exactly what a user would have to do. In this case that would be to click on the JS widget, then click on the correct choice which appears. You don't show the actual HTML of the dropdown which appears when the widget is clicked on (it gets dynamically appended to the end of the document) but something along the lines of

find('span.select2-selection__arrow').click # click on the dropdown arrow to open the selection choices
find('li.select2-results__option', text: 'VISA 4242 2021/4').click # click on the option to select it

should probably work (the class names may need to be adjusted if you've changed the default select2 configuration).


Note: Given your description the code select('VISA 4242 2020/10').select_option should have raised an error about not being able to find an element (since the select is hidden). Reasons why it wouldn't could be

  1. You've changed Capybara from its default of ignoring hidden elements (bad idea to do that for app testing)
  2. You aren't actually using capybara-webkit as the driver for this test
  3. There's an error causing the JS on your page not to run (JS syntax error, not transpiling/polyfilling to ES5 compatibility levels required by capybara-webkit, etc).

So if you haven't done the first of those, you might want to look into the other two (and if you have done the first consider reverting that if you want your tests to be meaningful).