mercredi 30 octobre 2019

Capybara test makes Rails throw DoubleRender error in Test environment, never occurs in Development

In a website, I have a modal, where a row from a table it contains can be selected, and a Submit button is then pressed. The button action makes an ajax POST to a server controller to create a new data structure. The controller then returns a JSON string, which contains the path, to which the Javascript will then redirect the user.

When I manually test this in the Development environment, it works fine and it has never thrown any errors at all. When I however run a test with Capybara, which simulates the same behaviour, the controller throws the error: "Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and at most once per action. Also note that neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like "redirect_to(...) and return". What's weird, is that it is completely unpredictable - sometimes, the error is thrown, and sometimes it isn't and the test passes. I cannot find any pattern in the behaviour, seems completely random. It also occurs when I insert a pause in the test and try to do it manually. Again, the error appears randomly. The error is caused by the last line in my controller function add_subset, which calls the render json:.

My controller code:

def add_subset
   authorize Thesaurus, :edit?
   results = Thesaurus.history_uris(identifier: the_params[:identifier], scope: IsoNamespace.find(the_params[:scope_id]))
   thesaurus = Thesaurus.find_minimum(results.first)
   thesaurus = edit_item(thesaurus)
   new_mc = thesaurus.add_subset(the_params[:concept_id])
   path = edit_subset_thesauri_managed_concept_path(new_mc, source_mc: new_mc.subsets_links.to_id, context_id: params[:ctxt_id])
   render json: { redirect_path: path }, :status => 200 

Ajax POST

$.ajax({
    url: "/thesauri/"+data["scope_id"]+"/add_subset",
    type: "POST",
    data: JSON.stringify({thesauri: data, ctxt_id: context_id}),
    dataType: 'json',
    contentType: 'application/json',
    error: function (xhr, status, error) {
      displayError("An error has occurred.");
    },
    success: function(result) {
      window.location = result["redirect_path"];
    }
});

Test

   [...]    
   find(:xpath, "//tr[contains(.,'C85494')]/td/a", :text => 'Show').click
   wait_for_ajax
   expect(page).to have_content("PKUNIT")
   click_link "Subsets"
   expect(page).to have_content("No subsets found.")
   click_button "+ New subset"
   expect(page).to have_content("Select Terminology")
   find(:xpath, "//*[@id='thTable']/tbody/tr[1]/td[1]").click
   click_button "Select"
   wait_for_ajax
   expect(page).to have_content("Edit Subset")

Does anyone have any idea what could possibly cause this?

Aucun commentaire:

Enregistrer un commentaire