I'm making my first Rails app, so this is probably basic.
In my user profiles, I want to let users add a title and description. I made them attributes of the User
model and added this to routes.rb
:
resources :users do
member do
post 'update_description'
end
end
The same method (not written yet) would handle both attributes. To practice TDD, I wanted to write a test that would simply show that, if the user submits a title, then the controller saves it to the database. I thought that would be an integration test, but I couldn't get the path right. (Should it be an integration test?) But then, with research, I managed to write a working post
statement in a related controller test file. Here's the controller test:
test "profile submits new title and description successfully" do
log_in_as(@user)
get :show, id: @user
assert_nil @user.title
post :update_description, id: @user, params: { title: "Lorem ipsum" }
# Next:
# @admin.reload.title
# assert @admin.title == "Lorem ipsum"
# assert_template 'users/show'
# Etc.
end
This raises the following error:
ERROR["test_profile_submits_new_title_and_description_successfully", UsersControllerTest, 2017-10-22 21:42:52 -0400]
test_profile_submits_new_title_and_description_successfully#UsersControllerTest (1508722972.17s)
ActionView::MissingTemplate: ActionView::MissingTemplate: Missing template users/update_description, application/update_description with {:locale=>[:en], :formats=>[:html], :variants=>[], :handlers=>[:erb, :builder, :raw, :ruby, :coffee, :jbuilder]}. Searched in:
* "/var/lib/gems/2.3.0/gems/web-console-2.0.0.beta3/lib/action_dispatch/templates"
* "/home/globewalldesk/startthis/app/views"
* "/var/lib/gems/2.3.0/gems/web-console-2.0.0.beta3/app/views"
test/controllers/users_controller_test.rb:83:in `block in <class:UsersControllerTest>'
test/controllers/users_controller_test.rb:83:in `block in <class:UsersControllerTest>'
I gather that this means Rails is looking for a view file and can't find one, but I don't see why post :update_description
has it looking for a view...I thought it would be posting info without a view (I have a similar route that works the same way with no view). The update_description
method is in the Users
controller. I've done a lot of research but I cannot figure out what am I doing wrong. Help! TIA.
The way you write test it looks as a Integration test. But I personally would advice to write a System test. Because I see you create a update_description
member route just to update User object? Thats not necessary - your User
resource has edit
and update
actions already, so you can remove that member route.
Integration testing used to check workflows and how interacts different parts of the app. While System check is for user interactions - basically you check things that user would do and see in his browser. Also it appears to me much simpler to write test in this technique (at least at this level).
So your system test would look like:
setup do
log_in_as(@user) // or what ever code to visit login page and login user
end
test "profile submits new title successfully" do
visit edit_user_path
fill_in "Title", with: "Lorem ipsum"
click_on "Save"
assert_response :redirect
follow_redirect!
assert_select "Title", text: "Lorem ipsum"
end
This assumes that after user submits his form, app redirects to user_path(@user)
(show page).
And Integration test would look something like:
test "profile submits new title successfully" do
log_in_as(@user) // or what ever code to login user
get "/user/#{@user.id}/edit"
assert_response :success
updated_title = "Lorem ipsum"
patch :update, user: { id: @user.id, title: updated_title }
assert_response :redirect
follow_redirect!
assert_response :success
assert_select "Title", text: "Lorem ipsum"
end
Note - I haven't tested this and I use Capybara and other tools, but not Minitest. But in this simple this should work I think.
And check the docs if you havent done that yet..