
Let’s see how to test views that have Turbo frames updated with Hotwire.
I am now generating a model in my Rails application. The model name is Document and it represents a document. Ultimately, the document will have an actual uploaded file, but for now, the Document model will only have a name and a description.
rails g model Document name description:text invoke active_record create db/migrate/20220725172353_create_documents.rb create app/models/document.rb invoke test_unit create test/models/document_test.rb create test/fixtures/documents.yml
After creating the database table with rails db:migrate I can add a system test before creating the controller actions and views.
I will generate the test with a Rails generator:
rails generate system_test Document invoke test_unit create test/system/documents_test.rb
This will create a new skeleton system test similar to this:
# test/system/documents_test.rb require "application_system_test_case" class DocumentsTest < ApplicationSystemTestCase # test "visiting the index" do # visit documents_url # # assert_selector "h1", text: "Document" # end end
Testing document index and show views
Before creating a document, I want to make sure I can view the list of all my documents (the index page), and the detailed view of one single document (the show page).
For this purpose, I create the first test, which clicks on a link in the document index page and views the show page which shows the document details. In the show page I expect to see an h1 tag with the document name.
This test, and the ones that follow, will use Rails fixtures to set up the objects to test.
The fixtures file was auto generated by Rails when we created this test, and has content similar to this:
# test/fixtures/documents.yml one: name: Document name description: This is the first document. two: name: MyString description: MyText
This lets us reference to the first fixture with the following code in the setup section of the test file:
# test/system/documents_test.rb class DocumentsTest < ApplicationSystemTestCase setup do @document = documents(:one) end end
Here’s the full test:
# test/system/documents_test.rb class DocumentsTest < ApplicationSystemTestCase setup do @document = documents(:one) end test "showing a document" do visit documents_path click_link @document.name assert_selector "h1", text: @document.name end end
If I run the test now, with rails test:system, I get an error, because we don’t yet have a route to the documents index page:
Error: DocumentsTest#test_showing_a_document: NameError: undefined local variable or method `documents_path'
I can add the routes for index and show with this syntax:
# config/routes.rb resources :documents, only: [:index, :show]
Re-running the test shows that we are missing the whole DocumentsController:
Error: DocumentsTest#test_showing_a_document: ActionController::RoutingError: uninitialized constant DocumentsController
After adding the controller file and the index action in it:
# app/controllers/documents_controller.rb class DocumentsController < ApplicationController def index end end
The test now shows I am missing the view template:
Error: DocumentsTest#test_showing_a_document: ActionController::MissingExactTemplate: DocumentsController#index is missing a template for request formats: text/html
Adding the view template:
mkdir app/views/documents touch app/views/documents/index.html.erb
Finally, we are getting somewhere. We can see the page, but it’s empty, and there is no link to the first document:
Error: DocumentsTest#test_showing_a_document: Capybara::ElementNotFound: Unable to find link "Document name"
Adding the link to the document in the view and the documents collection in the controller:
# app/controllers/documents_controller.rb class DocumentsController < ApplicationController def index @documents = Document.all end end# app/views/documents/index.html.erb <% @documents.each do |document| %> <div><%= link_to document.name, document_path(document) %></div> <% end %>
If I run the test at this point, it tells me I am missing the show action.
DocumentsTest#test_showing_a_document: AbstractController::ActionNotFound: The action 'show' could not be found for DocumentsController
I am then adding the action to the controller, and the corresponding view:
# app/controllers/documents_controller.rb class DocumentsController < ApplicationController ... def show @document = Document.find(params[:id]) end end# app/views/documents/show.html.erb <h1><%= @document.name %></h1>
And with these changes, the test passes.
Great! I have added a model, views and a controller with the index and show actions, but I still have to test creating a document using Turbo Drive.
This will be the topic of my next post.
Photo by Pixabay from Pexels
Check out my site at www.ferrariwebdevelopment.com for more blog posts and insights.
Photo by Pixabay from Pexels
Check out my site at www.ferrariwebdevelopment.com for more blog posts and insights.