diff options
| -rw-r--r-- | core/test/support/browser_integration_test.rb | 81 | ||||
| -rw-r--r-- | core/test/support/rack_test.rb (renamed from users/test/integration/api/rack_test.rb) | 4 | ||||
| -rw-r--r-- | test/test_helper.rb | 73 | ||||
| -rw-r--r-- | users/test/integration/api/account_flow_test.rb | 114 | ||||
| -rw-r--r-- | users/test/integration/api/login_test.rb | 3 | ||||
| -rw-r--r-- | users/test/integration/api/pgp_key_test.rb | 35 | ||||
| -rw-r--r-- | users/test/integration/api/srp_test.rb | 83 | ||||
| -rw-r--r-- | users/test/support/integration_test_helper.rb | 12 | 
8 files changed, 231 insertions, 174 deletions
| diff --git a/core/test/support/browser_integration_test.rb b/core/test/support/browser_integration_test.rb new file mode 100644 index 0000000..2885c3a --- /dev/null +++ b/core/test/support/browser_integration_test.rb @@ -0,0 +1,81 @@ +# +# BrowserIntegrationTest +# +# Use this class for capybara based integration tests for the ui. +# + +class BrowserIntegrationTest < ActionDispatch::IntegrationTest + +  CONFIG_RU = (Rails.root + 'config.ru').to_s +  OUTER_APP = Rack::Builder.parse_file(CONFIG_RU).first + +  require 'capybara/poltergeist' + +  Capybara.register_driver :rack_test do |app| +    Capybara::RackTest::Driver.new(app) +  end + +  Capybara.register_driver :poltergeist do |app| +    Capybara::Poltergeist::Driver.new(app) +  end + +  # this is integration testing. So let's make the whole +  # rack stack available... +  Capybara.app = OUTER_APP +  Capybara.run_server = true +  Capybara.app_host = 'http://lvh.me:3003' +  Capybara.server_port = 3003 +  Capybara.javascript_driver = :poltergeist +  Capybara.default_wait_time = 5 + + +  # Make the Capybara DSL available +  include Capybara::DSL + +  setup do +    Capybara.current_driver = Capybara.javascript_driver +    page.driver.add_headers 'ACCEPT-LANGUAGE' => 'en-EN' +  end + +  teardown do +    Capybara.reset_sessions!    # Forget the (simulated) browser state +    Capybara.use_default_driver # Revert Capybara.current_driver to Capybara.default_driver +  end + +  def submit_signup(username = nil, password = nil) +    username ||= "test_#{SecureRandom.urlsafe_base64}".downcase +    password ||= SecureRandom.base64 +    visit '/users/new' +    fill_in 'Username', with: username +    fill_in 'Password', with: password +    fill_in 'Password confirmation', with: password +    click_on 'Sign Up' +    return username, password +  end + +  add_teardown_hook do |testcase| +    unless testcase.passed? +      testcase.save_state +    end +  end + +  def save_state +    page.save_screenshot screenshot_path +    File.open(logfile_path, 'w') do |test_log| +      test_log.puts self.class.name +      test_log.puts "=========================" +      test_log.puts __name__ +      test_log.puts Time.now +      test_log.puts current_path +      test_log.puts page.status_code +      test_log.puts page.response_headers +      test_log.puts "page.html" +      test_log.puts "------------------------" +      test_log.puts page.html +      test_log.puts "server log" +      test_log.puts "------------------------" +      test_log.puts `tail log/test.log -n 200` +    end +  end + +end diff --git a/users/test/integration/api/rack_test.rb b/core/test/support/rack_test.rb index 9a69f52..0476cf7 100644 --- a/users/test/integration/api/rack_test.rb +++ b/core/test/support/rack_test.rb @@ -3,7 +3,11 @@ class RackTest < ActiveSupport::TestCase    include Warden::Test::Helpers    include LeapWebCore::AssertResponses +  CONFIG_RU = (Rails.root + 'config.ru').to_s +  OUTER_APP = Rack::Builder.parse_file(CONFIG_RU).first +    def app      OUTER_APP    end +  end diff --git a/test/test_helper.rb b/test/test_helper.rb index 3fb2716..f63591f 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -10,74 +10,6 @@ Dir["#{File.dirname(__FILE__)}/../*/test/support/**/*.rb"].each { |f| require f  class ActiveSupport::TestCase    # Add more helper methods to be used by all tests here... -  def file_path(name) -    File.join(Rails.root, 'test', 'files', name) -  end - -end - -require 'capybara/poltergeist' - -CONFIG_RU = (Rails.root + 'config.ru').to_s -OUTER_APP = Rack::Builder.parse_file(CONFIG_RU).first - -Capybara.register_driver :rack_test do |app| -  Capybara::RackTest::Driver.new(app) -end - -Capybara.register_driver :poltergeist do |app| -  Capybara::Poltergeist::Driver.new(app) -end - -# this is integration testing. So let's make the whole -# rack stack available... -Capybara.app = OUTER_APP -Capybara.run_server = true -Capybara.app_host = 'http://lvh.me:3003' -Capybara.server_port = 3003 -Capybara.javascript_driver = :poltergeist -Capybara.default_wait_time = 5 - -class BrowserIntegrationTest < ActionDispatch::IntegrationTest -  # Make the Capybara DSL available -  include Capybara::DSL -  include IntegrationTestHelper - -  setup do -    Capybara.current_driver = Capybara.javascript_driver -    page.driver.add_headers 'ACCEPT-LANGUAGE' => 'en-EN' -  end - -  teardown do -    Capybara.reset_sessions!    # Forget the (simulated) browser state -    Capybara.use_default_driver # Revert Capybara.current_driver to Capybara.default_driver -  end - -  add_teardown_hook do |testcase| -    unless testcase.passed? -      testcase.save_state -    end -  end - -  def save_state -    page.save_screenshot screenshot_path -    File.open(logfile_path, 'w') do |test_log| -      test_log.puts self.class.name -      test_log.puts "=========================" -      test_log.puts __name__ -      test_log.puts Time.now -      test_log.puts current_path -      test_log.puts page.status_code -      test_log.puts page.response_headers -      test_log.puts "page.html" -      test_log.puts "------------------------" -      test_log.puts page.html -      test_log.puts "server log" -      test_log.puts "------------------------" -      test_log.puts `tail log/test.log -n 200` -    end -  end -    protected    def logfile_path @@ -87,4 +19,9 @@ class BrowserIntegrationTest < ActionDispatch::IntegrationTest    def screenshot_path      Rails.root + 'tmp' + "#{self.class.name.underscore}.#{__name__}.png"    end + +  def file_path(name) +    File.join(Rails.root, 'test', 'files', name) +  end +  end diff --git a/users/test/integration/api/account_flow_test.rb b/users/test/integration/api/account_flow_test.rb index edd0859..b56d07b 100644 --- a/users/test/integration/api/account_flow_test.rb +++ b/users/test/integration/api/account_flow_test.rb @@ -1,50 +1,10 @@  require 'test_helper' -require_relative 'rack_test' +require_relative 'srp_test' -class AccountFlowTest < RackTest +class AccountFlowTest < SrpTest    setup do -    @login = "integration_test_user" -    Identity.find_by_address(@login + '@' + APP_CONFIG[:domain]).tap{|i| i.destroy if i} -    User.find_by_login(@login).tap{|u| u.destroy if u} -    @password = "srp, verify me!" -    @srp = SRP::Client.new @login, :password => @password -    @user_params = { -      :login => @login, -      :password_verifier => @srp.verifier.to_s(16), -      :password_salt => @srp.salt.to_s(16) -    } -    post 'http://api.lvh.me:3000/1/users.json', :user => @user_params -    @user = User.find_by_login(@login) -  end - -  teardown do -    if @user.reload -      @user.identity.destroy -      @user.destroy -    end -    Warden.test_reset! -  end - -  # this test wraps the api and implements the interface the ruby-srp client. -  def handshake(login, aa) -    post "http://api.lvh.me:3000/1/sessions.json", -      :login => login, -      'A' => aa, -      :format => :json -    response = JSON.parse(last_response.body) -    if response['errors'] -      raise RECORD_NOT_FOUND.new(response['errors']) -    else -      return response['B'] -    end -  end - -  def validate(m) -    put "http://api.lvh.me:3000/1/sessions/" + @login + '.json', -      :client_auth => m, -      :format => :json -    return JSON.parse(last_response.body) +    register_user    end    test "signup response" do @@ -53,25 +13,22 @@ class AccountFlowTest < RackTest    end    test "signup and login with srp via api" do -    server_auth = @srp.authenticate(self) +    authenticate      assert last_response.successful?      assert_nil server_auth["errors"]      assert server_auth["M2"]    end    test "signup and wrong password login attempt" do -    srp = SRP::Client.new @login, :password => "wrong password" -    server_auth = srp.authenticate(self) +    authenticate password: "wrong password"      assert_json_error "base" => "Not a valid username/password combination"      assert !last_response.successful?      assert_nil server_auth["M2"]    end    test "signup and wrong username login attempt" do -    srp = SRP::Client.new "wrong_login", :password => @password -    server_auth = nil      assert_raises RECORD_NOT_FOUND do -      server_auth = srp.authenticate(self) +      authenticate login: "wrong login"      end      assert_json_error "base" => "Not a valid username/password combination"      assert !last_response.successful? @@ -79,58 +36,31 @@ class AccountFlowTest < RackTest    end    test "update password via api" do -    @srp.authenticate(self) -    @password = "No! Verify me instead." -    @srp = SRP::Client.new @login, :password => @password -    @user_params = { -    #  :login => @login, -      :password_verifier => @srp.verifier.to_s(16), -      :password_salt => @srp.salt.to_s(16) -    } -    put "http://api.lvh.me:3000/1/users/" + @user.id + '.json', -      :user => @user_params, -      :format => :json -    server_auth = @srp.authenticate(self) +    authenticate +    update_user password: "No! Verify me instead." +    authenticate      assert last_response.successful?      assert_nil server_auth["errors"]      assert server_auth["M2"]    end +  test "change login with password_verifier" do +    authenticate +    new_login = 'zaph' +    cleanup_user new_login +    update_user login: new_login, password: @password +    assert last_response.successful? +    assert_equal new_login, @user.reload.login +  end +    test "prevent changing login without changing password_verifier" do -    server_auth = @srp.authenticate(self) +    authenticate      original_login = @user.login      new_login = 'zaph' -    User.find_by_login(new_login).try(:destroy) -    Identity.by_address.key(new_login + '@' + APP_CONFIG[:domain]).each do |identity| -      identity.destroy -    end -    put "http://api.lvh.me:3000/1/users/" + @user.id + '.json', :user => {:login => new_login}, :format => :json +    cleanup_user new_login +    update_user login: new_login      assert last_response.successful?      # does not change login if no password_verifier is present -    assert_equal original_login, @user.login -  end - -  test "upload pgp key" do -    server_auth = @srp.authenticate(self) -    key = FactoryGirl.build :pgp_key -    put "http://api.lvh.me:3000/1/users/" + @user.id + '.json', :user => {:public_key => key}, :format => :json -    assert_equal key, Identity.for(@user).keys[:pgp] +    assert_equal original_login, @user.reload.login    end - -  # eventually probably want to remove most of this into a non-integration -  # functional test -  test "prevent uploading invalid key" do -    server_auth = @srp.authenticate(self) -    put "http://api.lvh.me:3000/1/users/" + @user.id + '.json', :user => {:public_key => :blah}, :format => :json -    assert_nil Identity.for(@user).keys[:pgp] -  end - -  test "prevent emptying public key" do -    server_auth = @srp.authenticate(self) -    key = FactoryGirl.build :pgp_key -    put "http://api.lvh.me:3000/1/users/" + @user.id + '.json', :user => {:public_key => key}, :format => :json -    put "http://api.lvh.me:3000/1/users/" + @user.id + '.json', :user => {:public_key => ""}, :format => :json -    assert_equal key, Identity.for(@user).keys[:pgp] -  end -  end diff --git a/users/test/integration/api/login_test.rb b/users/test/integration/api/login_test.rb index fb761e5..a760d38 100644 --- a/users/test/integration/api/login_test.rb +++ b/users/test/integration/api/login_test.rb @@ -1,7 +1,6 @@  require 'test_helper' -require_relative 'rack_test' -class AccountFlowTest < RackTest +class LoginTest < RackTest    setup do      @login = "integration_test_user" diff --git a/users/test/integration/api/pgp_key_test.rb b/users/test/integration/api/pgp_key_test.rb new file mode 100644 index 0000000..4c7fb4c --- /dev/null +++ b/users/test/integration/api/pgp_key_test.rb @@ -0,0 +1,35 @@ +require 'test_helper' +require_relative 'srp_test' + +class PgpKeyTest < SrpTest + +  setup do +    # todo: prepare user and login without doing the srp dance +    register_user +    authenticate +  end + +  test "upload pgp key" do +    update_user public_key: key +    assert_equal key, Identity.for(@user).keys[:pgp] +  end + +  # eventually probably want to remove most of this into a non-integration +  # functional test +  test "prevent uploading invalid key" do +    update_user public_key: "invalid key" +    assert_nil Identity.for(@user).keys[:pgp] +  end + +  test "prevent emptying public key" do +    update_user public_key: key +    update_user public_key: "" +    assert_equal key, Identity.for(@user).keys[:pgp] +  end + +  protected + +  def key +    @key ||= FactoryGirl.build :pgp_key +  end +end diff --git a/users/test/integration/api/srp_test.rb b/users/test/integration/api/srp_test.rb new file mode 100644 index 0000000..b291269 --- /dev/null +++ b/users/test/integration/api/srp_test.rb @@ -0,0 +1,83 @@ +class SrpTest < RackTest + +  teardown do +    if @user +      cleanup_user +    end +    Warden.test_reset! +  end + +  # this test wraps the api and implements the interface the ruby-srp client. +  def handshake(login, aa) +    post "http://api.lvh.me:3000/1/sessions.json", +      :login => login, +      'A' => aa, +      :format => :json +    response = JSON.parse(last_response.body) +    if response['errors'] +      raise RECORD_NOT_FOUND.new(response['errors']) +    else +      return response['B'] +    end +  end + +  def validate(m) +    put "http://api.lvh.me:3000/1/sessions/" + @login + '.json', +      :client_auth => m, +      :format => :json +    return JSON.parse(last_response.body) +  end + +  protected + +  attr_reader :server_auth + +  def register_user(login = "integration_test_user", password = 'srp, verify me!') +    cleanup_user(login) +    post 'http://api.lvh.me:3000/1/users.json', +      user: user_params(login: login, password: password), +      format: :json +    @user = User.find_by_login(login) +    @login = login +    @password = password +  end + +  def update_user(params) +    put "http://api.lvh.me:3000/1/users/" + @user.id + '.json', +      :user => user_params(params), +      :format => :json +  end + +  def authenticate(params = nil) +    @server_auth = srp(params).authenticate(self) +  end + +  def cleanup_user(login = nil) +    login ||= @user.login +    Identity.by_address.key(login + '@' + APP_CONFIG[:domain]).each do |identity| +      identity.destroy +    end +    if user = User.find_by_login(login) +      user.destroy +    end +  end + +  def user_params(params) +    # if there is no srp magic needed just return the params +    return params unless params.keys.include?(:password) +    params.reverse_merge! login: @login, salt: @salt +    @srp = SRP::Client.new params[:login], password: params.delete(:password) +    @salt = srp.salt.to_s(16) +    params.merge :password_verifier => srp.verifier.to_s(16), +      :password_salt => @salt +  end + +  def srp(params = nil) +    if params.nil? +      @srp +    else +      params.reverse_merge! password: @password +      SRP::Client.new(params.delete(:login) || @login, params) +    end +  end +end diff --git a/users/test/support/integration_test_helper.rb b/users/test/support/integration_test_helper.rb deleted file mode 100644 index 51e47c6..0000000 --- a/users/test/support/integration_test_helper.rb +++ /dev/null @@ -1,12 +0,0 @@ -module IntegrationTestHelper -  def submit_signup(username = nil, password = nil) -    username ||= "test_#{SecureRandom.urlsafe_base64}".downcase -    password ||= SecureRandom.base64 -    visit '/users/new' -    fill_in 'Username', with: username -    fill_in 'Password', with: password -    fill_in 'Password confirmation', with: password -    click_on 'Sign Up' -    return username, password -  end -end | 
