5

I'm new with Minitest and Apartment and have difficulties to configure the environment correctly to run the test cases. I want to make acceptance testing using Capybara & Selenium. When I run my tests I get following error message:

Apartment::TenantNotFound:         Apartment::TenantNotFound: One of the following schema(s) is invalid: "test-tenant" "public"

So it seems tenant is not created correctly. Apartment gem has instructions of how to use it with Rspec but I don't know how to make similar setup in Minitest. How should tenants be defined so Minitest can see them?

My test_helpers.rb:

ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
require "minitest/reporters"
require "minitest/rails/capybara"
Minitest::Reporters.use!

class ActiveSupport::TestCase
  # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
  fixtures :all
end

class ActionController::TestCase
  include Devise::TestHelpers
end

class ActionDispatch::IntegrationTest
end

And the test case:

require "test_helper"

class LoginTest < Capybara::Rails::TestCase
  def setup
    Apartment::Tenant.drop( "test-tenant" ) rescue nil
    Apartment::Tenant.create( "test-tenant" ) rescue nil
    Apartment::Tenant.switch!( "test-tenant" )

    # Since we are using Apartment gem, we need to tell Capybara to connect our testing tenant URL + port number
    Capybara.server_port = 5000
    Capybara.always_include_port = true
    Capybara.app_host = "http://test-tenant.lvh.me"
  end

  feature "Login" do
    scenario "with correct credentials", js: true do
      visit '/accounts/sign_in'
      fill_in("account[email]", with: "#{accounts(:tenant_user).email}")
      fill_in("account[password]", with: "password")
      click_button("Sign in")
      page.must_have_content("Signed in successfully.")

      visit '/'
      page.must_have_content("Welcome")
    end
  end

end
talakoski
  • 131
  • 1
  • 8

2 Answers2

2

I figured the answer out myself after testing some different combinations. The solution is actually quite simple. All Apartment & Capybara related configs should be defined in test_helpers.rb file.

test_helpers.rb:

ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
require "minitest/reporters"
require "minitest/rails/capybara"
Minitest::Reporters.use!


Apartment::Tenant.drop( "test-tenant" ) rescue nil
Apartment::Tenant.create( "test-tenant" ) rescue nil
Apartment::Tenant.switch!( "test-tenant" )


class ActiveSupport::TestCase
  # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
  fixtures :all
end

class ActionController::TestCase
  include Devise::TestHelpers
end

class ActionDispatch::IntegrationTest
end

# Since we are using Apartment gem, we need to tell Capybara to connect our testing tenant URL + port number
Capybara.server_port = 5000
Capybara.always_include_port = true
Capybara.app_host = "http://test-tenant.lvh.me"

test case is simply:

require "test_helper"


class LoginTest < Capybara::Rails::TestCase

  def setup
  end


  feature "Login" do
    scenario "with correct credentials", js: true do
      visit '/accounts/sign_in'
      fill_in("account[email]", with: "#{accounts(:tenant_user).email}")
      fill_in("account[password]", with: "password")
      click_button("Sign in")
      page.must_have_content("Signed in successfully.")

      visit '/'
      page.must_have_content("Welcome")
    end
  end

end
talakoski
  • 131
  • 1
  • 8
  • Is this approach good enough to speed up rails test with minitest? I had a horrible time with testing apartment with minitest, because I had to create tenant every time test method is called. – elquimista Feb 13 '17 at 18:57
  • My point is that following your method, tenant is created only once for one test cycle? Or is it created before every test case? – elquimista Feb 13 '17 at 18:58
  • Tenant is created only once. It will then run all the migrations to create the tables for the tenant. – talakoski Mar 21 '17 at 10:11
  • yeah I confirmed it by doing some experiment. thanks for your answer – elquimista Mar 21 '17 at 13:09
1

The Apartment gem wiki recommends the following configuration in your spec_helper or rails_helper:

RSpec.configure do |config|
  config.before(:suite) do
    # Clean all tables to start
    DatabaseCleaner.clean_with :truncation
    # Use transactions for tests
    DatabaseCleaner.strategy = :transaction
    # Truncating doesn't drop schemas, ensure we're clean here, app *may not* exist
    Apartment::Tenant.drop('app') rescue nil
    # Create the default tenant for our tests
    Company.create!(name: 'Influitive Corp.', subdomain: 'app')
  end

  config.before(:each) do
    # Start transaction for this test
    DatabaseCleaner.start
    # Switch into the default tenant
    Apartment::Tenant.switch! 'app'
  end

  config.after(:each) do
    # Reset tentant back to `public`
    Apartment::Tenant.reset
    # Rollback transaction
    DatabaseCleaner.clean
  end
end

This works for me, and has the benefit of not requiring duplicate code in tests.

When I used this same config I did run into an issue though when the test used AJAX with selenium. Then I come up against the Apartment::TenantNotFound error even though the config works perfect for no JS formatted tests.

dual88
  • 57
  • 10