Building Mortimer, day 1

This post is about 6 years due – I cannot remedy that but I can tell you the story up until this moment, and as I move forward, I will let you in on every bump on the road 😇

Clean sheet, volume 4

Did you skip the story? Not sure if you will miss out on any big findings, but should you reconsider – well the link stays 😄

Day 1

Volume 4 is 'the bluebox' and my first task is the mundane one (adding the Devise gem) which I'm not sure if there's any reason for diving too much into [ed. but I ended up somewhere between two bar stools, so there you go] . Here's a post I used for making sure I did not skip the important (moving) parts.

Note to self!
When testing stuff it's important whether you write new_user_session_url or new_user_session_path – that your configuration files are correct, otherwise you'll see something along the lines of:

hmm - why example.com and not localhost

Look for example.com in your config/ files - most likely in environments/test.rb or application.rb if you've been tinkering 😉 I've listed it in item 3 below.

Testing the implementation of Devise functionality is not necessary (José Valim ad the rest of Plataformatec and contributors to Devise did a formidable job already) but testing the implementation of Devise in your app certainly is hence I had to find out how to test the as a logged in/out user I want to... something.

Turns out there are a few things to remember:

  1. Add encrypted password to your users.yml file
    <%= encrypted_password:%=Devise::Encryptor.digest(User,ENV['TEST_PASSWORD']) %>
    and the ENV value will have to be add somewhere not pushed to the GitHub repo. Read about environment variables here. I went with .env.test and inserted a single line (so far) like this: TEST_PASSWORD=w12345678
  2. Add include Devise::Test::IntegrationHelpers to test/test_helper.rb right at the bottom where they say you can add things like this.
  3. Make sure to add/edit these two lines to config/environments/test.rb
  config.action_mailer.default_url_options = { host: "localhost", port: 3000 }
  config.action_controller.default_url_options = { host: "localhost", port: 3000 }
  1. Now edit your test/controllers/pages_controller_test.rb to include a test for each of the three most important use cases [ sign_in, sign_out, sign_up ] utilizing the Devise helpers like so:
  test "should get home and login path" do
    get root_url
    assert_response :success
    assert_select "a[href=?]", new_user_session_url
  end
  
  test "should get home and signout path" do
    sign_in users(:one)
    get root_url
    assert_response :success
    assert_select "a[href=?]", destroy_user_session_url
  end
  
  test "should get home and sign-up path" do
    get root_url
    assert_response :success
    assert_select "a[href=?]", new_user_registration_url
  end
  1. Watch them fail one by one and then let's go work them green!

The "should get home and signout path" fails because we do not (yet) test for a signed in user! make views/pages/index.html.erb look like this:

<% if user_signed_in? %>
  <h1>Welcome Home, <%= current_user.email %></h1>
  <%= link_to 'Sign out', destroy_user_session_url, data: { turbo_method: :delete } %> %>
<% else %>
  <h1>Home</h1>
  <%= link_to 'Sign in', new_user_session_url %>
<% end %>

If everything else is a-o-k you should at least see one more green test. You may not be 100% in-the-know with line 3 right above here, but Rails 7 going forward utilizes Turbo to the Max so to say. That means this 'link_to' will be a POST with the special _method sauce that Rails is so good at sprinkling all over the entire framework. Read more here.

  1. Nailing the last test will take yet another line in the views/pages/index.html.erb file
  ...
  <%= link_to 'Sign in', new_user_session_url %>
  <%= link_to 'Sign up', new_user_registration_url %>
<% end %>

And just like this we managed to implement the 3 more important request paths. Guess it's time for a ☕ and committing with a tag=basic_devise –

  1. left one test out (which turned out to be quite important) though 😲. Run a system test like this:
require "application_system_test_case"

class DevisesTest < ApplicationSystemTestCase
  test "visiting the index" do
    visit root_url
    click_on "Sign up"

    fill_in "Email", with: "mike_hammer@miami.vice"
    fill_in "Password", with: "w12345678"
    fill_in "Password confirmation", with: "w12345678"
    click_on "Sign up"

    assert_text "You have signed up successfully"
    click_on "Sign out"

    assert_text "Sign in"
    click_on "Sign in"

    fill_in "Email", with: "mike_hammer@miami.vice"
    fill_in "Password", with: "w12345678"
    click_on "Log in"

    assert_text "Sign out"
    click_on "Sign out"

    assert_text "Sign in"
  end
end

This, however, turned out NOT to be that easy! I kept getting a really weird error:

Email has already been taken!

'till this moment I'm not sure why - but I figured a way around (debugging the test showed only the two expected users from my users.yml) which required a minor rewrite:

require "application_system_test_case"

class DevisesTest < ApplicationSystemTestCase
  test "visiting the index" do
    unique = DateTime.now.strftime("%Q")
    visit root_url
    click_on "Sign up"

    fill_in "Email", with: "mike_hammer_#{unique}@miami.vice"
    ...

    fill_in "Email", with: "mike_hammer_#{unique}@miami.vice"
    ...
  end
end

- and that was the end of day 1, sort of, but that's a different post 😄

Walther H Diechmann

Walther H Diechmann

Got on the train just about when the IBM PC 5150 got introduced and never really got off again - switched to macOS about 2006 though, and never looked back. It's been such a ride!
Silkeborg, Denmark