Search code examples
ember.jsember-clijquery-chosenacceptance-testing

Ember acceptance test for chosen-select


Chosen is working great for me but I cannot figure out how to get my acceptance test to send in the value on the form submit.

Handlebars template:

<form>
  {{#ember-chosen value=country}}
    {{#each countries as |country|}}
      <option value={{country}}>{{country}}</option>
    {{/each}}
  {{/ember-chosen}}
  {{#link-to 'countries.show' (query-params country=country) tagName='button' type='submit' replace=true class="submit__button"}}Search{{/link-to}}
</form>

Acceptance test:

test 'Searching for a country', (assert) ->
  visit '/search'
  find('.chosen-select').val('USA')
  find('.chosen-select').trigger('chosen:updated')
  click('.submit__button')
  andThen ->
    assert.equal find(".chosen-select :selected").text(), "USA"

This fails because on submit country is not even passed in as a query param, but only in the test.

The same thing happens if I do it in the console. If I open my console and do:

$('.chosen-select').val('USA')
$('.chosen-select').trigger('chosen:updated')

then the selection updates before my eyes! But then clicking submit produces the same results as the test, that is, the country is not passed into the query-params.

Clicking "USA" from the dropdown however, then clicking submit, works perfectly.

UPDATE

Chad Carbert's response below gave me the answer. Here are the specific results:

$('.chosen-select').val('USA')
$('.chosen-select').trigger('chosen:updated')

updates the DOM only. Not the data-bindings with Ember.

$('.chosen-select').trigger('change', {'selected': 'USA'})

updates the data-bindings (which is what I really need), not the DOM. Since this is for my acceptance tests only and I don't need to see the DOM change, my test now looks like this:

test 'Searching for a country', (assert) ->
  visit '/search'
  find('.chosen-select').trigger('change', {'selected': 'USA'})
  click('.submit__button')
  andThen ->
    assert.equal find(".chosen-select :selected").text(), "USA"

Which works like a charm! If you wanted to though, there would be no harm in doing all three:

test 'Searching for a country', (assert) ->
  visit '/search'
  find('.chosen-select').val('USA')
  find('.chosen-select').trigger('chosen:updated')
  find('.chosen-select').trigger('change', {'selected': 'USA'})
  click('.submit__button')
  andThen ->
    assert.equal find(".chosen-select :selected").text(), "USA"

Thank you Chad!


Solution

  • It looks like this might be an issue with the way that this component wraps the jQuery library. Looking at the documentation for chosen:

    Updating Chosen Dynamically If you need to update the options in your select field and want Chosen to pick up the changes, you'll need to trigger the "chosen:updated" event on the field. Chosen will re-build itself based on the updated content. via chosen docs

    However, it doesn't look like the ember component is wrapping that event in any way. It also looks like the chosen:update is updating the chosen UI implementation, but not the data binding within Ember. This would be in a case where you've after the fact added options to the select, and want these reflected ('rebuilt') on the screen.

    Looking at the code behind this component and how it's wrapping the chosen library, it appears that this component is only capturing the change event. So try doing a trigger on a change event and that should have things update within ember, and its data binding.

    Or try triggering the change the way it's mentioned on the Chosen docs:

    Form Field Change** When working with form fields, you often want to perform some behavior after a value has been selected or deselected. Whenever a user selects a field in Chosen, it triggers a "change" event* on the original form field. That let's you do something like this: $("#form_field").chosen().change( … );

    If that doesn't work, if you're able to provide a codepen I will take a look closer, thanks!