jeudi 15 août 2019

Rails with Devise: user details not being updated in tests (but works in application)

I'm writing some tests for a new Rails application, and have a test that is failing for reasons I can't understand. The test is for updating the user profile details, which is controlled by the Devise registrations_controller. I have not over-ridden this part of the controller so the code there is vanilla. The application itself works - I can update a user profile with no issues. But, when I run my test, it fails.

Test code:

sign_in @admin
get user_path(@admin)
assert_response :success
assert_template 'users/show'
assert_select "p.user-name", text: @admin.name
assert_select "p.user-email", text: @admin.email
#Can edit own user profile
new_name="New name"
put user_registration_path, params: {user: {name: new_name, email: @admin.email, current_password: 'password123'}}
get user_path(@admin)
assert_select "p.user-name", text: new_name

Fixture:

admin:
  id: 11
  email: $LABEL@example.com
  name: $LABEL
  slug: $LABEL
  encrypted_password: <%= Devise::Encryptor.digest(User, 'password123') %>
  admin: true
  organisation_id: 1

When I run the test, it produces an error at the final assert_select of "<New name> expected but was <admin>.. Expected 0 to be >= 1.", showing that the record hasn't been updated.

Extensive use of byebug shows that the error is caused because the record isn't being updated within the Devise update controller, leading to it going down the else route at line 57. However, I can't see why this isn't working in the tests when I can update profiles in the application!

If I replace the put ... line with @admin.update_columns(name: new_name) then the test passes, so it definitely looks like something's wrong with my put command, which is odd because the same line works in a previous Rails application. (And I've tried patch with the same results, although the working form in the application uses put which is why I've stuck with that in the test.)

The working form code from the application (with HTML cruft stripped out):

<%= form_for(@user, url: registration_path(@user), html: { method: :put, id: 'edit-user-account' }) do |f| %>
    <%= f.label :name %><br/>
    <%= f.text_field :name, autofocus: true, autocomplete: "Name", class: "form-control form-control-lg" %>

    <%= f.label :email %><br/>
    <%= f.email_field :email, autofocus: true, autocomplete: "email@example.com", class: "form-control form-control-lg" %>

    <%= f.label :password %>
    <i>(leave blank if you don't want to change it)</i><br/>
    <%= f.password_field :password, autocomplete: "new-password", class: "form-control form-control-lg" %>

    <%= f.label :password_confirmation %><br/>
    <%= f.password_field :password_confirmation, autocomplete: "new-password", class: "form-control form-control-lg" %>

    <%= f.label :current_password %>
    <%= f.password_field :current_password, autocomplete: "current-password", class: "form-control form-control-lg" %>

    <%= f.submit "Update", class: "btn btn-lg btn-primary" %>
<% end %>


Any advice gratefully received!

Ruby 2.6.3, Rails 5.2.3, Devise 4.6.2, minitest 5.11.3, rails-controller-testing 1.0.2

Aucun commentaire:

Enregistrer un commentaire