blue_light_special 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. data/LICENSE +20 -0
  2. data/README.rdoc +67 -0
  3. data/Rakefile +95 -0
  4. data/VERSION +1 -0
  5. data/app/controllers/blue_light_special/impersonations_controller.rb +44 -0
  6. data/app/controllers/blue_light_special/passwords_controller.rb +84 -0
  7. data/app/controllers/blue_light_special/sessions_controller.rb +70 -0
  8. data/app/controllers/blue_light_special/users_controller.rb +48 -0
  9. data/app/models/blue_light_special_mailer.rb +22 -0
  10. data/app/models/deliver_change_password_job.rb +19 -0
  11. data/app/models/deliver_welcome_job.rb +17 -0
  12. data/app/models/impersonation.rb +26 -0
  13. data/app/views/blue_light_special_mailer/change_password.html.erb +9 -0
  14. data/app/views/impersonations/index.html.erb +5 -0
  15. data/app/views/passwords/edit.html.erb +23 -0
  16. data/app/views/passwords/new.html.erb +15 -0
  17. data/app/views/sessions/new.html.erb +48 -0
  18. data/app/views/users/_form.html.erb +21 -0
  19. data/app/views/users/edit.html.erb +6 -0
  20. data/app/views/users/new.html.erb +6 -0
  21. data/app/views/users/show.html.erb +8 -0
  22. data/generators/blue_light_special/USAGE +1 -0
  23. data/generators/blue_light_special/blue_light_special_generator.rb +78 -0
  24. data/generators/blue_light_special/lib/insert_commands.rb +33 -0
  25. data/generators/blue_light_special/lib/rake_commands.rb +22 -0
  26. data/generators/blue_light_special/templates/README +20 -0
  27. data/generators/blue_light_special/templates/application.html.erb +50 -0
  28. data/generators/blue_light_special/templates/blue_light_special.rb +21 -0
  29. data/generators/blue_light_special/templates/blue_light_special.yml +42 -0
  30. data/generators/blue_light_special/templates/factories.rb +23 -0
  31. data/generators/blue_light_special/templates/migrations/create_users.rb +24 -0
  32. data/generators/blue_light_special/templates/migrations/update_users.rb +44 -0
  33. data/generators/blue_light_special/templates/style.css +31 -0
  34. data/generators/blue_light_special/templates/user.rb +3 -0
  35. data/generators/blue_light_special/templates/xd_receiver.html +10 -0
  36. data/generators/blue_light_special/templates/xd_receiver_ssl.html +10 -0
  37. data/generators/blue_light_special_admin/USAGE +1 -0
  38. data/generators/blue_light_special_admin/blue_light_special_admin_generator.rb +30 -0
  39. data/generators/blue_light_special_admin/lib/insert_commands.rb +33 -0
  40. data/generators/blue_light_special_admin/templates/README +16 -0
  41. data/generators/blue_light_special_admin/templates/app/controllers/admin/admin_controller.rb +14 -0
  42. data/generators/blue_light_special_admin/templates/app/controllers/admin/users_controller.rb +52 -0
  43. data/generators/blue_light_special_admin/templates/app/views/admin/users/_form.html.erb +25 -0
  44. data/generators/blue_light_special_admin/templates/app/views/admin/users/edit.html.erb +6 -0
  45. data/generators/blue_light_special_admin/templates/app/views/admin/users/index.html.erb +7 -0
  46. data/generators/blue_light_special_admin/templates/app/views/admin/users/new.html.erb +6 -0
  47. data/generators/blue_light_special_admin/templates/app/views/admin/users/show.html.erb +10 -0
  48. data/generators/blue_light_special_admin/templates/test/integration/admin/users_test.rb +201 -0
  49. data/generators/blue_light_special_tests/USAGE +1 -0
  50. data/generators/blue_light_special_tests/blue_light_special_tests_generator.rb +21 -0
  51. data/generators/blue_light_special_tests/templates/README +58 -0
  52. data/generators/blue_light_special_tests/templates/test/integration/edit_profile_test.rb +35 -0
  53. data/generators/blue_light_special_tests/templates/test/integration/facebook_test.rb +61 -0
  54. data/generators/blue_light_special_tests/templates/test/integration/impersonation_test.rb +39 -0
  55. data/generators/blue_light_special_tests/templates/test/integration/password_reset_test.rb +128 -0
  56. data/generators/blue_light_special_tests/templates/test/integration/sign_in_test.rb +66 -0
  57. data/generators/blue_light_special_tests/templates/test/integration/sign_out_test.rb +28 -0
  58. data/generators/blue_light_special_tests/templates/test/integration/sign_up_test.rb +47 -0
  59. data/lib/blue_light_special.rb +7 -0
  60. data/lib/blue_light_special/authentication.rb +138 -0
  61. data/lib/blue_light_special/configuration.rb +32 -0
  62. data/lib/blue_light_special/extensions/errors.rb +6 -0
  63. data/lib/blue_light_special/extensions/rescue.rb +5 -0
  64. data/lib/blue_light_special/routes.rb +55 -0
  65. data/lib/blue_light_special/user.rb +241 -0
  66. data/rails/init.rb +4 -0
  67. data/shoulda_macros/blue_light_special.rb +244 -0
  68. data/test/controllers/passwords_controller_test.rb +184 -0
  69. data/test/controllers/sessions_controller_test.rb +129 -0
  70. data/test/controllers/users_controller_test.rb +57 -0
  71. data/test/models/blue_light_special_mailer_test.rb +52 -0
  72. data/test/models/impersonation_test.rb +25 -0
  73. data/test/models/user_test.rb +213 -0
  74. data/test/rails_root/app/controllers/accounts_controller.rb +10 -0
  75. data/test/rails_root/app/controllers/application_controller.rb +6 -0
  76. data/test/rails_root/app/helpers/application_helper.rb +5 -0
  77. data/test/rails_root/app/helpers/confirmations_helper.rb +2 -0
  78. data/test/rails_root/app/helpers/passwords_helper.rb +2 -0
  79. data/test/rails_root/app/models/user.rb +3 -0
  80. data/test/rails_root/config/boot.rb +110 -0
  81. data/test/rails_root/config/environment.rb +22 -0
  82. data/test/rails_root/config/environments/development.rb +19 -0
  83. data/test/rails_root/config/environments/production.rb +1 -0
  84. data/test/rails_root/config/environments/test.rb +37 -0
  85. data/test/rails_root/config/initializers/blue_light_special.rb +4 -0
  86. data/test/rails_root/config/initializers/inflections.rb +10 -0
  87. data/test/rails_root/config/initializers/mime_types.rb +5 -0
  88. data/test/rails_root/config/initializers/requires.rb +13 -0
  89. data/test/rails_root/config/initializers/time_formats.rb +4 -0
  90. data/test/rails_root/config/routes.rb +9 -0
  91. data/test/rails_root/db/migrate/20100305173127_blue_light_special_create_users.rb +21 -0
  92. data/test/rails_root/db/migrate/20100305173129_create_delayed_jobs.rb +20 -0
  93. data/test/rails_root/public/dispatch.rb +10 -0
  94. data/test/rails_root/script/create_project.rb +52 -0
  95. data/test/rails_root/test/factories/user.rb +13 -0
  96. data/test/rails_root/test/functional/accounts_controller_test.rb +23 -0
  97. data/test/rails_root/test/integration/facebook_test.rb +49 -0
  98. data/test/rails_root/test/integration/impersonation_test.rb +38 -0
  99. data/test/rails_root/test/integration/password_reset_test.rb +127 -0
  100. data/test/rails_root/test/integration/sign_in_test.rb +72 -0
  101. data/test/rails_root/test/integration/sign_out_test.rb +28 -0
  102. data/test/rails_root/test/integration/sign_up_test.rb +84 -0
  103. data/test/test_helper.rb +21 -0
  104. metadata +219 -0
@@ -0,0 +1,22 @@
1
+ require File.join(File.dirname(__FILE__), 'boot')
2
+ require 'digest/md5'
3
+
4
+ Rails::Initializer.run do |config|
5
+ config.load_paths += Dir.glob(File.join(RAILS_ROOT, 'vendor', 'gems', '*', 'lib'))
6
+ config.action_controller.session = {
7
+ :session_key => "_blue_light_special_session",
8
+ :secret => ['blue_light_special', 'random', 'words', 'here'].map {|k| Digest::MD5.hexdigest(k) }.join
9
+ }
10
+
11
+ config.gem "justinfrench-formtastic",
12
+ :lib => 'formtastic',
13
+ :source => 'http://gems.github.com'
14
+
15
+ config.gem "mini_fb",
16
+ :version => '=0.2.2'
17
+
18
+ config.gem "delayed_job",
19
+ :version => '=1.8.4'
20
+
21
+ config.action_mailer.default_url_options = { :host => 'localhost:3000' }
22
+ end
@@ -0,0 +1,19 @@
1
+ # Settings specified here will take precedence over those in config/environment.rb
2
+
3
+ # In the development environment your application's code is reloaded on
4
+ # every request. This slows down response time but is perfect for development
5
+ # since you don't have to restart the webserver when you make code changes.
6
+ config.cache_classes = false
7
+
8
+ # Log error messages when you accidentally call methods on nil.
9
+ config.whiny_nils = true
10
+
11
+ # Show full error reports and disable caching
12
+ config.action_controller.consider_all_requests_local = true
13
+ config.action_controller.perform_caching = false
14
+ config.action_view.debug_rjs = true
15
+
16
+ # Don't care if the mailer can't send
17
+ config.action_mailer.raise_delivery_errors = false
18
+
19
+ HOST = "localhost"
@@ -0,0 +1 @@
1
+ HOST = "http://example.com"
@@ -0,0 +1,37 @@
1
+ # Settings specified here will take precedence over those in config/environment.rb
2
+
3
+ # The test environment is used exclusively to run your application's
4
+ # test suite. You never need to work with it otherwise. Remember that
5
+ # your test database is "scratch space" for the test suite and is wiped
6
+ # and recreated between test runs. Don't rely on the data there!
7
+ config.cache_classes = true
8
+
9
+ # Log error messages when you accidentally call methods on nil.
10
+ config.whiny_nils = true
11
+
12
+ # Show full error reports and disable caching
13
+ config.action_controller.consider_all_requests_local = true
14
+ config.action_controller.perform_caching = false
15
+
16
+ # Disable request forgery protection in test environment
17
+ config.action_controller.allow_forgery_protection = false
18
+
19
+ # Tell ActionMailer not to deliver emails to the real world.
20
+ # The :test delivery method accumulates sent emails in the
21
+ # ActionMailer::Base.deliveries array.
22
+ config.action_mailer.delivery_method = :test
23
+
24
+ config.gem 'shoulda',
25
+ :source => "http://gemcutter.org",
26
+ :version => '>= 2.9.1'
27
+ config.gem 'factory_girl',
28
+ :source => "http://gemcutter.org",
29
+ :version => '>= 1.2.3'
30
+
31
+ config.gem 'webrat',
32
+ :lib => false,
33
+ :version => '>= 0.6.0'
34
+
35
+ config.gem 'fakeweb',
36
+ :source => "http://gemcutter.org",
37
+ :version => '>= 1.2.8'
@@ -0,0 +1,4 @@
1
+ BlueLightSpecial.configure do |config|
2
+ config.mailer_sender = 'donotreply@example.com'
3
+ config.impersonation_hash = 'REPLACE WITH A LONG HASH HERE'
4
+ end
@@ -0,0 +1,10 @@
1
+ # Be sure to restart your server when you modify this file.
2
+
3
+ # Add new inflection rules using the following format
4
+ # (all these examples are active by default):
5
+ # Inflector.inflections do |inflect|
6
+ # inflect.plural /^(ox)$/i, '\1en'
7
+ # inflect.singular /^(ox)en/i, '\1'
8
+ # inflect.irregular 'person', 'people'
9
+ # inflect.uncountable %w( fish sheep )
10
+ # end
@@ -0,0 +1,5 @@
1
+ # Be sure to restart your server when you modify this file.
2
+
3
+ # Add new mime types for use in respond_to blocks:
4
+ # Mime::Type.register "text/richtext", :rtf
5
+ # Mime::Type.register_alias "text/html", :iphone
@@ -0,0 +1,13 @@
1
+ Dir[File.join(RAILS_ROOT, 'lib', 'extensions', '*.rb')].each do |f|
2
+ require f
3
+ end
4
+
5
+ Dir[File.join(RAILS_ROOT, 'lib', '*.rb')].each do |f|
6
+ require f
7
+ end
8
+
9
+ # Rails 2 doesn't like mocks
10
+
11
+ Dir[File.join(RAILS_ROOT, 'test', 'mocks', RAILS_ENV, '*.rb')].each do |f|
12
+ require f
13
+ end
@@ -0,0 +1,4 @@
1
+ # Example time formats
2
+ { :short_date => "%x", :long_date => "%a, %b %d, %Y" }.each do |k, v|
3
+ ActiveSupport::CoreExtensions::Time::Conversions::DATE_FORMATS.update(k => v)
4
+ end
@@ -0,0 +1,9 @@
1
+ ActionController::Routing::Routes.draw do |map|
2
+ map.namespace :admin do |admin|
3
+ admin.resources :users
4
+ end
5
+ map.resource :account
6
+ map.root :controller => 'accounts', :action => 'edit'
7
+
8
+ BlueLightSpecial::Routes.draw(map)
9
+ end
@@ -0,0 +1,21 @@
1
+ class BlueLightSpecialCreateUsers < ActiveRecord::Migration
2
+ def self.up
3
+ create_table(:users) do |t|
4
+ t.string :email
5
+ t.string :role, :limit => 50
6
+ t.string :encrypted_password, :limit => 128
7
+ t.string :salt, :limit => 128
8
+ t.string :remember_token, :limit => 128
9
+ t.string :facebook_uid, :limit => 50
10
+ t.string :password_reset_token, :limit => 128
11
+ t.timestamps
12
+ end
13
+
14
+ add_index :users, :email
15
+ add_index :users, :remember_token
16
+ end
17
+
18
+ def self.down
19
+ drop_table :users
20
+ end
21
+ end
@@ -0,0 +1,20 @@
1
+ class CreateDelayedJobs < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :delayed_jobs, :force => true do |table|
4
+ table.integer :priority, :default => 0 # Allows some jobs to jump to the front of the queue
5
+ table.integer :attempts, :default => 0 # Provides for retries, but still fail eventually.
6
+ table.text :handler # YAML-encoded string of the object that will do work
7
+ table.text :last_error # reason for last failure (See Note below)
8
+ table.datetime :run_at # When to run. Could be Time.now for immediately, or sometime in the future.
9
+ table.datetime :locked_at # Set when a client is working on this object
10
+ table.datetime :failed_at # Set when all retries have failed (actually, by default, the record is deleted instead)
11
+ table.string :locked_by # Who is working on this object (if locked)
12
+ table.timestamps
13
+ end
14
+
15
+ end
16
+
17
+ def self.down
18
+ drop_table :delayed_jobs
19
+ end
20
+ end
@@ -0,0 +1,10 @@
1
+ #!/opt/local/bin/ruby
2
+
3
+ require File.dirname(__FILE__) + "/../config/environment" unless defined?(RAILS_ROOT)
4
+
5
+ # If you're using RubyGems and mod_ruby, this require should be changed to an absolute path one, like:
6
+ # "/usr/local/lib/ruby/gems/1.8/gems/rails-0.8.0/lib/dispatcher" -- otherwise performance is severely impaired
7
+ require "dispatcher"
8
+
9
+ ADDITIONAL_LOAD_PATHS.reverse.each { |dir| $:.unshift(dir) if File.directory?(dir) } if defined?(Apache::RubyRun)
10
+ Dispatcher.dispatch
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ require 'activesupport'
4
+ require 'pathname'
5
+
6
+ project_name = ARGV[0]
7
+ fail("Usage: #{File.basename(__FILE__)} new_project_name") unless project_name
8
+ fail("Project name must only contain [a-z0-9_]") unless project_name =~ /^[a-z0-9_]+$/
9
+
10
+ base_directory = Pathname.new(File.join(File.dirname(__FILE__), '..', '..')).realpath
11
+ project_directory = base_directory + project_name
12
+ fail("Project directory (#{project_directory}) already exists") if project_directory.exist?
13
+
14
+ template_url = "git@github.com:thoughtbot/rails-template.git"
15
+ changeme = "CHANGEME"
16
+
17
+ def run(cmd)
18
+ puts "Running '#{cmd}'"
19
+ out = `#{cmd}`
20
+ if $? != 0
21
+ fail "Command #{cmd} failed: #$?\n#{out}"
22
+ end
23
+ out
24
+ end
25
+
26
+ def search_and_replace(file, search, replace)
27
+ if File.file?(file)
28
+ contents = File.read(file)
29
+ if contents[search]
30
+ puts "Replacing #{search} with #{replace} in #{file}"
31
+ contents.gsub!(search, replace)
32
+ File.open(file, "w") { |f| f << contents }
33
+ end
34
+ end
35
+ end
36
+
37
+ run("mkdir #{project_directory}")
38
+ Dir.chdir(project_directory) or fail("Couldn't change to #{project_directory}")
39
+ run("git init")
40
+ run("git remote add template #{template_url}")
41
+ run("git pull template master")
42
+
43
+ Dir.glob("#{project_directory}/**/*").each do |file|
44
+ search_and_replace(file, changeme, project_name)
45
+ end
46
+
47
+ run("git commit -a -m 'Initial commit'")
48
+
49
+ puts
50
+ puts "Now login to github and add a new project named '#{project_name.humanize.titleize}'"
51
+
52
+
@@ -0,0 +1,13 @@
1
+ Factory.sequence :email do |n|
2
+ "user#{n}@example.com"
3
+ end
4
+
5
+ Factory.define :user do |user|
6
+ user.email { Factory.next :email }
7
+ user.password { "password" }
8
+ user.password_confirmation { "password" }
9
+ end
10
+
11
+ Factory.define :admin_user, :parent => :user do |admin|
12
+ admin.role 'admin'
13
+ end
@@ -0,0 +1,23 @@
1
+ require 'test_helper'
2
+
3
+ class AccountsControllerTest < ActionController::TestCase
4
+
5
+ context "when signed out" do
6
+ setup { sign_out }
7
+ should_deny_access_on :get, :edit
8
+ should_deny_access_on :put, :update
9
+ end
10
+
11
+ context "on POST to create" do
12
+ setup do
13
+ post :create
14
+ end
15
+
16
+ should_deny_access
17
+
18
+ should "not store location" do
19
+ assert session[:return_to].nil?
20
+ end
21
+ end
22
+
23
+ end
@@ -0,0 +1,49 @@
1
+ require 'test_helper'
2
+ require 'facebooker/mock/service'
3
+ require 'facebooker/mock/session'
4
+
5
+ class FacebookTest < ActionController::IntegrationTest
6
+
7
+ context 'Signing in with Facebook' do
8
+
9
+ setup do
10
+ Facebooker::MockService.fixture_path = File.dirname(__FILE__) + '/../facebooker_fixtures'
11
+ fb_session = Facebooker::MockSession.create
12
+ fb_session.secure!
13
+ CitiesController.any_instance.stubs(:facebook_session).returns(fb_session)
14
+ end
15
+
16
+ should 'find an existing user with the facebook uid' do
17
+ user = Factory( :facebook_user,
18
+ :facebook_uid => 8055,
19
+ :email => 'bob@facebook.com',
20
+ :first_name => 'Bob',
21
+ :last_name => 'Jones',
22
+ :display_name => 'Bob Jones',
23
+ :zip_code => '11111')
24
+
25
+ visit city_url(City.default)
26
+ assert controller.signed_in?
27
+ assert_equal controller.current_user, user
28
+ end
29
+
30
+ should 'create a new user when the facebook uid is not found' do
31
+ assert_nil User.find_by_facebook_uid(8055)
32
+
33
+ visit city_url(City.default)
34
+ assert controller.signed_in?
35
+ assert_equal controller.current_user.facebook_uid, 8055
36
+ end
37
+
38
+ should 'copy the facebook user details' do
39
+ visit city_url(City.default)
40
+ assert controller.signed_in?
41
+ assert_equal controller.current_user.first_name, 'Dave'
42
+ assert_equal controller.current_user.last_name, 'Fetterman'
43
+ assert_equal controller.current_user.display_name, 'Dave Fetterman'
44
+ assert_equal controller.current_user.email, 'bob@facebook.com'
45
+ end
46
+
47
+ end
48
+
49
+ end
@@ -0,0 +1,38 @@
1
+ require 'test_helper'
2
+
3
+ class ImpersonationTest < ActionController::IntegrationTest
4
+
5
+ context 'When impersonating another user' do
6
+
7
+ setup do
8
+ @bob = Factory(:user, :email => 'bob@bob.bob', :display_name => 'Bobby')
9
+ @admin_user = Factory(:admin_user, :email => 'admin@twongo.com')
10
+ sign_in_as @admin_user.email, @admin_user.password
11
+ impersonate(@bob)
12
+ end
13
+
14
+ should 'be signed in' do
15
+ assert controller.signed_in?
16
+ end
17
+
18
+ should 'be logged in as bob' do
19
+ assert_equal controller.current_user, @bob
20
+ end
21
+
22
+ should 'be able to go back to the original admin user' do
23
+ delete impersonate_url
24
+ assert controller.signed_in?
25
+ assert_equal controller.current_user, @admin_user
26
+ end
27
+
28
+ end
29
+
30
+
31
+ private
32
+
33
+
34
+ def impersonate(user)
35
+ post impersonate_url(user)
36
+ end
37
+
38
+ end
@@ -0,0 +1,127 @@
1
+ require 'test_helper'
2
+
3
+ class PasswordResetTest < ActionController::IntegrationTest
4
+
5
+ context 'When requesting a password reset' do
6
+
7
+ setup do
8
+ ActionMailer::Base.deliveries.clear
9
+ end
10
+
11
+ teardown do
12
+ ActionMailer::Base.deliveries.clear
13
+ end
14
+
15
+ context 'when not signed up' do
16
+
17
+ should 'see "Unknown email"' do
18
+ request_password_reset('unknown@bob.bob')
19
+ assert_match(/Unknown email/, response.body)
20
+ end
21
+
22
+ should 'not send an email' do
23
+ request_password_reset('unknown@bob.bob')
24
+ assert ActionMailer::Base.deliveries.empty?
25
+ end
26
+
27
+ end
28
+
29
+ context 'when signed up' do
30
+
31
+ setup do
32
+ @user = Factory(:user, :email => 'bob@bob.bob')
33
+ end
34
+
35
+ should 'see "instructions for changing your password"' do
36
+ request_password_reset(@user.email)
37
+ assert_match(/instructions for changing your password/, response.body)
38
+ end
39
+
40
+ should 'send a password reset email to the user' do
41
+ request_password_reset(@user.email)
42
+ @user.reload # catch updated confirmation token
43
+ Delayed::Job.work_off
44
+ sent = ActionMailer::Base.deliveries.last
45
+ assert_equal @user.email, sent.recipients
46
+ assert_match /password/i, sent.subject
47
+ assert !@user.password_reset_token.blank?
48
+ assert_match /#{@user.password_reset_token}/, sent.body[:url]
49
+ end
50
+
51
+ end
52
+
53
+ end
54
+
55
+ context 'After requesting a password reset' do
56
+
57
+ setup do
58
+ ActionMailer::Base.deliveries.clear
59
+ @user = Factory(:user, :email => 'bob@bob.bob')
60
+ end
61
+
62
+ teardown do
63
+ ActionMailer::Base.deliveries.clear
64
+ end
65
+
66
+ context 'with failed password confirmation' do
67
+
68
+ should 'see error messages' do
69
+ request_password_reset('bob@bob.bob')
70
+ @user.reload
71
+ change_password(@user, :password => 'goodpassword', :confirm => 'badpassword')
72
+ assert_match(/Password doesn't match confirmation/, response.body)
73
+ end
74
+
75
+ should 'not be signed in' do
76
+ request_password_reset('bob@bob.bob')
77
+ @user.reload
78
+ change_password(@user, :password => 'goodpassword', :confirm => 'badpassword')
79
+ assert !controller.signed_in?
80
+ end
81
+
82
+ end
83
+
84
+ context 'with valid password and confirmation' do
85
+
86
+ should 'be signed in' do
87
+ request_password_reset('bob@bob.bob')
88
+ @user.reload
89
+ change_password(@user)
90
+ assert controller.signed_in?
91
+ end
92
+
93
+ should 'be able to sign in with new password' do
94
+ request_password_reset('bob@bob.bob')
95
+ @user.reload
96
+ change_password(@user)
97
+ sign_out
98
+ sign_in_as('bob@bob.bob', 'goodpassword')
99
+ assert controller.signed_in?
100
+ end
101
+
102
+ end
103
+
104
+ end
105
+
106
+
107
+ private
108
+
109
+
110
+ def request_password_reset(email)
111
+ visit new_password_url
112
+ fill_in "Email Address", :with => email
113
+ click_button "reset password"
114
+ end
115
+
116
+ def change_password(user, options = {})
117
+ options[:password] ||= 'goodpassword'
118
+ options[:confirm] ||= options[:password]
119
+
120
+ visit edit_user_password_path(:user_id => user,
121
+ :token => user.password_reset_token)
122
+ fill_in "Choose password", :with => options[:password]
123
+ fill_in "Confirm password", :with => options[:confirm]
124
+ click_button "save this password"
125
+ end
126
+
127
+ end