From 374eb7bd3f369cba946d4b8002cd51a499aef32a Mon Sep 17 00:00:00 2001 From: Azul Date: Sun, 14 Jul 2013 14:28:35 +0200 Subject: js integration test for signup, login, logout --- common_dependencies.rb | 7 +++++++ test/test_helper.rb | 25 +++++++++++++++++++++++++ users/test/integration/browser/account_test.rb | 21 +++++++++++++++++++++ 3 files changed, 53 insertions(+) create mode 100644 users/test/integration/browser/account_test.rb diff --git a/common_dependencies.rb b/common_dependencies.rb index 63c3710..085a898 100644 --- a/common_dependencies.rb +++ b/common_dependencies.rb @@ -1,7 +1,14 @@ source "http://rubygems.org" group :test do + # moching and stubing gem 'mocha', '~> 0.13.0', :require => false + # integration testing + gem 'capybara' + # headless js integration testing + gem 'poltergeist' + # required for save_and_open_page in integration tests + # gem 'launchy' end group :test, :development do diff --git a/test/test_helper.rb b/test/test_helper.rb index 0016771..c6794f4 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -10,3 +10,28 @@ 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... end + +require 'capybara/poltergeist' +Capybara.javascript_driver = :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(OUTER_APP) +end + +# Transactional fixtures do not work with Selenium tests, because Capybara +# uses a separate server thread, which the transactions would be hidden +# from. We hence use DatabaseCleaner to truncate our test database. +class BrowserIntegrationTest < ActionDispatch::IntegrationTest + # Make the Capybara DSL available + include Capybara::DSL + + Capybara.app_host = 'http://localhost:3000' + Capybara.server_port = 3000 + teardown do + Capybara.reset_sessions! # Forget the (simulated) browser state + Capybara.use_default_driver # Revert Capybara.current_driver to Capybara.default_driver + end +end diff --git a/users/test/integration/browser/account_test.rb b/users/test/integration/browser/account_test.rb new file mode 100644 index 0000000..a112430 --- /dev/null +++ b/users/test/integration/browser/account_test.rb @@ -0,0 +1,21 @@ +class AccountTest < BrowserIntegrationTest + + setup do + Capybara.current_driver = Capybara.javascript_driver # :selenium by default + end + + test "normal account workflow" do + 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' + assert page.has_content?("Welcome #{username}"), + "failed to verify server. expected M2: #{page.evaluate_script("srp.session.getM2();")}" + click_on 'Logout' + assert_equal '/', current_path + end + +end -- cgit v1.2.3 From 740813d8350290c176c1b0d0cfe3ac80aee1b420 Mon Sep 17 00:00:00 2001 From: Azul Date: Sun, 14 Jul 2013 16:19:32 +0200 Subject: we do not expose M2 in srp.js anymore. So there is no way to print it. This message used to be correct but there are also other things that can cause this to fail now. So let's just remove it. --- users/app/assets/javascripts/srp | 2 +- users/test/integration/browser/account_test.rb | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/users/app/assets/javascripts/srp b/users/app/assets/javascripts/srp index 926a5d5..9c61d52 160000 --- a/users/app/assets/javascripts/srp +++ b/users/app/assets/javascripts/srp @@ -1 +1 @@ -Subproject commit 926a5d5960db51903e33c8496487da59f9f41242 +Subproject commit 9c61d52f1f975ec0eefe5b4a0b71ac529300cbe7 diff --git a/users/test/integration/browser/account_test.rb b/users/test/integration/browser/account_test.rb index a112430..4fff637 100644 --- a/users/test/integration/browser/account_test.rb +++ b/users/test/integration/browser/account_test.rb @@ -12,8 +12,7 @@ class AccountTest < BrowserIntegrationTest fill_in 'Password', with: password fill_in 'Password confirmation', with: password click_on 'Sign Up' - assert page.has_content?("Welcome #{username}"), - "failed to verify server. expected M2: #{page.evaluate_script("srp.session.getM2();")}" + assert page.has_content?("Welcome #{username}") click_on 'Logout' assert_equal '/', current_path end -- cgit v1.2.3 From 8b79988c4c6cedd77664e14f16b149a669965eff Mon Sep 17 00:00:00 2001 From: Azul Date: Sun, 14 Jul 2013 19:52:54 +0200 Subject: make sure capybara runs the whole rack app We use port 3003 for the integration test server. This test takes a few seconds (~8) now. Most of this is startup time of the server. A second run still takes 2 seconds like before. --- test/test_helper.rb | 20 +++++++++++++------- users/test/integration/api/rack_test.rb | 3 --- users/test/integration/browser/account_test.rb | 2 +- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/test/test_helper.rb b/test/test_helper.rb index c6794f4..a409b58 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -12,24 +12,30 @@ class ActiveSupport::TestCase end require 'capybara/poltergeist' -Capybara.javascript_driver = :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(OUTER_APP) + Capybara::RackTest::Driver.new(app) +end + +Capybara.register_driver :poltergeist do |app| + Capybara::Poltergeist::Driver.new(app) end -# Transactional fixtures do not work with Selenium tests, because Capybara -# uses a separate server thread, which the transactions would be hidden -# from. We hence use DatabaseCleaner to truncate our test database. +# 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 + class BrowserIntegrationTest < ActionDispatch::IntegrationTest # Make the Capybara DSL available include Capybara::DSL - Capybara.app_host = 'http://localhost:3000' - Capybara.server_port = 3000 teardown do Capybara.reset_sessions! # Forget the (simulated) browser state Capybara.use_default_driver # Revert Capybara.current_driver to Capybara.default_driver diff --git a/users/test/integration/api/rack_test.rb b/users/test/integration/api/rack_test.rb index da960f2..9a69f52 100644 --- a/users/test/integration/api/rack_test.rb +++ b/users/test/integration/api/rack_test.rb @@ -1,6 +1,3 @@ -CONFIG_RU = (Rails.root + 'config.ru').to_s -OUTER_APP = Rack::Builder.parse_file(CONFIG_RU).first - class RackTest < ActiveSupport::TestCase include Rack::Test::Methods include Warden::Test::Helpers diff --git a/users/test/integration/browser/account_test.rb b/users/test/integration/browser/account_test.rb index 4fff637..5483c89 100644 --- a/users/test/integration/browser/account_test.rb +++ b/users/test/integration/browser/account_test.rb @@ -1,7 +1,7 @@ class AccountTest < BrowserIntegrationTest setup do - Capybara.current_driver = Capybara.javascript_driver # :selenium by default + Capybara.current_driver = Capybara.javascript_driver end test "normal account workflow" do -- cgit v1.2.3 From 48db4caa2fff451ce9cbb1b52c895ea7136736a4 Mon Sep 17 00:00:00 2001 From: Azul Date: Mon, 15 Jul 2013 12:26:07 +0200 Subject: require test_helper from account test so it can be run in isolation --- users/test/integration/browser/account_test.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/users/test/integration/browser/account_test.rb b/users/test/integration/browser/account_test.rb index 5483c89..9f6d067 100644 --- a/users/test/integration/browser/account_test.rb +++ b/users/test/integration/browser/account_test.rb @@ -1,3 +1,5 @@ +require 'test_helper' + class AccountTest < BrowserIntegrationTest setup do -- cgit v1.2.3 From 9abb7dd66cf44051662bc3b8663e6492dd6d9953 Mon Sep 17 00:00:00 2001 From: Azul Date: Sun, 14 Jul 2013 15:55:01 +0200 Subject: prevent _ prefixes for couchDB document ids --- users/app/models/token.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/users/app/models/token.rb b/users/app/models/token.rb index 44a6dfe..cc62778 100644 --- a/users/app/models/token.rb +++ b/users/app/models/token.rb @@ -8,7 +8,7 @@ class Token < CouchRest::Model::Base def initialize(*args) super - self.id = SecureRandom.urlsafe_base64(32) + self.id = SecureRandom.urlsafe_base64(32).gsub(/^_*/, '') end design do -- cgit v1.2.3 From 6e47ea438cf35c6cad00e65e2817cb57d07db111 Mon Sep 17 00:00:00 2001 From: Azul Date: Tue, 16 Jul 2013 12:32:43 +0200 Subject: use ruby-srp 0.2.0 which has a hex based api --- users/leap_web_users.gemspec | 2 +- users/lib/warden/strategies/secure_remote_password.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/users/leap_web_users.gemspec b/users/leap_web_users.gemspec index 2f4b10c..d33328a 100644 --- a/users/leap_web_users.gemspec +++ b/users/leap_web_users.gemspec @@ -17,6 +17,6 @@ Gem::Specification.new do |s| s.add_dependency "leap_web_core", LeapWeb::VERSION - s.add_dependency "ruby-srp", "~> 0.1.7" + s.add_dependency "ruby-srp", "~> 0.2.0" s.add_dependency "rails_warden" end diff --git a/users/lib/warden/strategies/secure_remote_password.rb b/users/lib/warden/strategies/secure_remote_password.rb index a97e795..2c681be 100644 --- a/users/lib/warden/strategies/secure_remote_password.rb +++ b/users/lib/warden/strategies/secure_remote_password.rb @@ -36,7 +36,7 @@ module Warden end def validate - session[:handshake].authenticate(params['client_auth'].hex) + session[:handshake].authenticate(params['client_auth']) end def initialize! @@ -44,7 +44,7 @@ module Warden client = SRP::Client.new user.username, :verifier => user.verifier, :salt => user.salt - session[:handshake] = SRP::Session.new(client, params['A'].hex) + session[:handshake] = SRP::Session.new(client, params['A']) custom! json_response(session[:handshake]) else fail! :base => 'invalid_user_pass' -- cgit v1.2.3 From adfae07c5d682d9aaf09d1f33507e5f9c2b80976 Mon Sep 17 00:00:00 2001 From: Azul Date: Tue, 16 Jul 2013 12:36:56 +0200 Subject: to move to the next iteration use continue in js. --- users/app/assets/javascripts/users.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/users/app/assets/javascripts/users.js b/users/app/assets/javascripts/users.js index 65bed4f..4c9b510 100644 --- a/users/app/assets/javascripts/users.js +++ b/users/app/assets/javascripts/users.js @@ -49,12 +49,12 @@ for (field in message.errors) { if (field == 'base') { alert_message(message.errors[field]); - next; + continue; } error = message.errors[field]; element = $('form input[name$="[' + field + ']"]'); if (!element) { - next; + continue; } element.trigger('element:validate:fail.ClientSideValidations', error).data('valid', false); } -- cgit v1.2.3 From f40c09a8b750d5d317a22af7186bde5c940b6924 Mon Sep 17 00:00:00 2001 From: Azul Date: Tue, 16 Jul 2013 13:06:48 +0200 Subject: ensure the page has been reloaded before testing current_path This test would fail sometimes on assert_equal '/', current_path I believe it was a timing issue. page.has_content? will wait for the content to show up. So afterwards the current_path should always be correct. --- test/test_helper.rb | 1 + users/test/integration/browser/account_test.rb | 1 + 2 files changed, 2 insertions(+) diff --git a/test/test_helper.rb b/test/test_helper.rb index a409b58..26b99f4 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -31,6 +31,7 @@ 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 diff --git a/users/test/integration/browser/account_test.rb b/users/test/integration/browser/account_test.rb index 9f6d067..ce63baf 100644 --- a/users/test/integration/browser/account_test.rb +++ b/users/test/integration/browser/account_test.rb @@ -16,6 +16,7 @@ class AccountTest < BrowserIntegrationTest click_on 'Sign Up' assert page.has_content?("Welcome #{username}") click_on 'Logout' + assert page.has_content?("Sign Up") assert_equal '/', current_path end -- cgit v1.2.3 From 8486248a7a960bc75f25f2c5a00791416f124ac4 Mon Sep 17 00:00:00 2001 From: Azul Date: Tue, 16 Jul 2013 13:14:01 +0200 Subject: adapt srp account_flow test for the api to new ruby_srp API --- users/test/integration/api/account_flow_test.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/users/test/integration/api/account_flow_test.rb b/users/test/integration/api/account_flow_test.rb index f5cb0b1..4c94389 100644 --- a/users/test/integration/api/account_flow_test.rb +++ b/users/test/integration/api/account_flow_test.rb @@ -26,19 +26,19 @@ class AccountFlowTest < RackTest def handshake(login, aa) post "http://api.lvh.me:3000/1/sessions.json", :login => login, - 'A' => aa.to_s(16), + 'A' => aa, :format => :json response = JSON.parse(last_response.body) if response['errors'] raise RECORD_NOT_FOUND.new(response['errors']) else - return response['B'].hex + return response['B'] end end def validate(m) put "http://api.lvh.me:3000/1/sessions/" + @login + '.json', - :client_auth => m.to_s(16), + :client_auth => m, :format => :json return JSON.parse(last_response.body) end -- cgit v1.2.3