Search code examples
ruby-on-railsintegration-testingtestunitruby-on-rails-5

Multiple users in a rails integration test


I am looking how to do an integration for a flow that requires 2 users, in which you cannot JUMP around in the order.

User A does 1
User B does 2
User A does 3
User B does 4
User A does 5
... 

Test code is executed in a random order therefor; I cannot write a series of tests such as: test "user A does 1" do ... end and expect them to execute in sequence

So, how should an integration test be written for the above situtation?

require 'test_helper'

class MyIntegrationTest < ActionController::IntegrationTest

  test "Test interaction between 2 users" do 
    sign_in '[email protected]'
    assert_response :success

    get '/does/1'
    assert_response :success

    sign_out

    sign_in '[email protected]'
    assert_response :success

    get '/does/2'
    assert_response :success

    sign_out

    sign_in '[email protected]'
    assert_response :success

    get '/does/3'
    assert_response :success

    sign_out

    sign_in '[email protected]'
    # ahhhhhhhhhhhhhhhhhhhhhhhhhhh! .....
  end

Keep in mind, controller testing may be removed in Rails 5.

https://github.com/rails/rails/issues/18950#issuecomment-77924771

Found this in rails issues:

https://github.com/rails/rails/issues/22742

Solution

  • For the benefit of anyone else coming here: For some reason the relevant helpers seem to not be documented in the current Rails guides, but I found this example from https://guides.rubyonrails.org/v4.1/testing.html

    require 'test_helper'
    
    
    
    class UserFlowsTest < ActionDispatch::IntegrationTest
      test "login and browse site" do
        # User david logs in
        david = login(:david)
        # User guest logs in
        guest = login(:guest)
     
        # Both are now available in different sessions
        assert_equal 'Welcome david!', david.flash[:notice]
        assert_equal 'Welcome guest!', guest.flash[:notice]
     
        # User david can browse site
        david.browses_site
        # User guest can browse site as well
        guest.browses_site
     
        # Continue with other assertions
      end
     
      private
     
        module CustomDsl
          def browses_site
            get "/products/all"
            assert_response :success
            assert assigns(:products)
          end
        end
     
        def login(user)
          open_session do |sess|
            sess.extend(CustomDsl)
            u = users(user)
            sess.https!
            sess.post "/login", username: u.username, password: u.password
            assert_equal '/welcome', sess.path
            sess.https!(false)
          end
        end
    end
    

    This technique still seemed to work in a Rails 5.1 app.