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 |