thoughtbot / capybara-webkit

A Capybara driver for headless WebKit to test JavaScript web apps
https://thoughtbot.com/open-source
MIT License
1.97k stars 428 forks source link

Request sends before confirming modal #1026

Closed zacharyjt closed 6 years ago

zacharyjt commented 7 years ago

I'm testing a list view in my app where you can select multiple items then click a delete button. The button immediately opens a standard JS modal asking "Are you sure?". In my test, I use accept_confirm {} to perform the action, but it does not successfully delete the items. The request sends, and the page appears to do what it is supposed to, but my in-app success message states 0 items were deleted (and the items still exist). While debugging, I noticed there is a POST request to our /destroy route that occurs before the modal appears. In real browsers and other drivers (tried selenium and poltergeist), the POST request doesn't happen until after you confirm the modal. Not sure if that's what's causing the issue, but it's the only difference I've seen, and the same test works with the other drivers.

Any thoughts on what might be happening here?

twalpole commented 7 years ago

@zacharyjt Show the test code, my guess is you're using accept_confirm incorrectly.

zacharyjt commented 7 years ago

@twalpole Here's a snippet from the code where I select the two items, then click delete:

find("li[data-id='#{item.id}']>a").click
find("li[data-id='#{item2.id}']>div>label>span").click
accept_confirm { find('a.delete').click }

After this is when I get the "success" message informing me that 0 items were deleted (but should really be 2 items).

twalpole commented 7 years ago

Assuming that the click on 'a.delete' is what causes the confirm modal to appear, then your code is correct. If it's the click on the span that makes the confirm modal appear then it is not. Can you post the JS code that is calling window.confirm?

zacharyjt commented 6 years ago

@twalpole Yes, it is the click on 'a.delete' that prompts the confirm modal. Here is the js we call when clicking the button:

    handlePanelMultipleDeleteLinkClick: function(event) {
      var confirmMessage += ' ' + I18n.t('assets.confirm_delete');
      if (!confirm(confirmMessage)) {
        return false;
      }

      var destroyParams = {};

      if ($('input#q').val()) {
        destroyParams.q = $('input#q').val();
      }

      $tb.Notice.init(I18n.t('assets.panels.bulk_actions_dropdown.deleting'), 'loading');

      $.ajax({
        type: 'DELETE',
        url: '/assets/destroy',
        dataType: 'json',
        data: destroyParams
      }).done(function(data) {
        $tb.Assets.searchForm.submit();
        $tb.Notice.init(data.message, 'success');
        $tb.ListLayoutModule.removeSelectionMessage();
      });
      return false;
    }

"Assets" are the items I am deleting. Please let me know if you have any questions.

twalpole commented 6 years ago

Is this an event handler being registered by JQuery? If not, just returning false may not be doing what you think it is. If yes, and you are definitely using the standard system 'confirm' and not one a library has overwritten to give you a prettier 'confirm' modal - then I'm out of guesses.

zacharyjt commented 6 years ago

@twalpole Yes, this uses JQuery, but we have not overridden any of the defaults for the confirm modal. It's just whatever comes out of the box. After doing some additional digging though, I'm wondering if this is due to an existing issue with QT not sending params/bodies for certain requests (also, a correction from my original post, we are doing a DELETE request, not a POST). Here are some issues I believe are related: https://stackoverflow.com/questions/16044184/ajax-delete-request-not-sending-data-parameters-in-capybara-webkit https://stackoverflow.com/questions/27808826/capybara-webkit-doesnt-pass-params-from-angular#27860855

180

427

553

None of the described workarounds will work for me. I saw where someone said this had been fixed in QT 5.4, but I am using 5.5.1 and have verified that my rails controller is not receiving the data params sent in the line data: destroyParams. Any ideas on how I could work around this?

twalpole commented 6 years ago

@zacharyjt The DELETE issue is probably it. You can try using a newer Qt (5.8/5.9) (requires installing the qt-webkit package separately if available on your package or building Qt with qt-webkit enabled) or at this point you may just be better off swapping to using headless chrome with selenium, which doesn't have the issues of being equivalent to a 6-7 year old browser.

zacharyjt commented 6 years ago

@twalpole Tried rebuilding everything with qt5.9, but unfortunately still getting the same behavior. I would love to switch to headless chrome, but chromedriver currently has a bug that will not allow me to bypass ssl certificate errors. We use Ember, which must be run via https, but we don't have valid certs for local development, so that prevents me from testing a large portion of our app. For now, I think I'll just have to switch to selenium webdriver for the affected tests.