aihs_devise_invitable 0.4.rc

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. data/.gitignore +27 -0
  2. data/Gemfile +8 -0
  3. data/Gemfile.lock +117 -0
  4. data/LICENSE +20 -0
  5. data/README.rdoc +187 -0
  6. data/Rakefile +57 -0
  7. data/app/controllers/devise/invitations_controller.rb +47 -0
  8. data/app/views/devise/invitations/edit.html.erb +14 -0
  9. data/app/views/devise/invitations/new.html.erb +12 -0
  10. data/app/views/devise/mailer/invitation.html.erb +8 -0
  11. data/app/views/devise/mailer/invitation_instructions.html.erb +8 -0
  12. data/config/locales/en.yml +9 -0
  13. data/devise_invitable.gemspec +143 -0
  14. data/lib/devise_invitable.rb +16 -0
  15. data/lib/devise_invitable/controllers/helpers.rb +7 -0
  16. data/lib/devise_invitable/controllers/url_helpers.rb +24 -0
  17. data/lib/devise_invitable/mailer.rb +14 -0
  18. data/lib/devise_invitable/model.rb +130 -0
  19. data/lib/devise_invitable/rails.rb +13 -0
  20. data/lib/devise_invitable/routes.rb +13 -0
  21. data/lib/devise_invitable/schema.rb +33 -0
  22. data/lib/devise_invitable/version.rb +3 -0
  23. data/lib/generators/active_record/devise_invitable_generator.rb +13 -0
  24. data/lib/generators/active_record/templates/migration.rb +20 -0
  25. data/lib/generators/devise_invitable/devise_invitable_generator.rb +16 -0
  26. data/lib/generators/devise_invitable/install_generator.rb +35 -0
  27. data/lib/generators/devise_invitable/views_generator.rb +10 -0
  28. data/test/generators_test.rb +45 -0
  29. data/test/integration/invitation_test.rb +107 -0
  30. data/test/integration_tests_helper.rb +58 -0
  31. data/test/mailers/invitation_mail_test.rb +63 -0
  32. data/test/model_tests_helper.rb +41 -0
  33. data/test/models/invitable_test.rb +213 -0
  34. data/test/models_test.rb +32 -0
  35. data/test/rails_app/app/controllers/admins_controller.rb +6 -0
  36. data/test/rails_app/app/controllers/application_controller.rb +3 -0
  37. data/test/rails_app/app/controllers/home_controller.rb +4 -0
  38. data/test/rails_app/app/controllers/users_controller.rb +12 -0
  39. data/test/rails_app/app/helpers/application_helper.rb +2 -0
  40. data/test/rails_app/app/models/octopussy.rb +11 -0
  41. data/test/rails_app/app/models/user.rb +4 -0
  42. data/test/rails_app/app/views/home/index.html.erb +0 -0
  43. data/test/rails_app/app/views/layouts/application.html.erb +16 -0
  44. data/test/rails_app/app/views/users/invitations/new.html.erb +15 -0
  45. data/test/rails_app/config.ru +4 -0
  46. data/test/rails_app/config/application.rb +46 -0
  47. data/test/rails_app/config/boot.rb +14 -0
  48. data/test/rails_app/config/database.yml +22 -0
  49. data/test/rails_app/config/environment.rb +5 -0
  50. data/test/rails_app/config/environments/development.rb +26 -0
  51. data/test/rails_app/config/environments/production.rb +49 -0
  52. data/test/rails_app/config/environments/test.rb +35 -0
  53. data/test/rails_app/config/initializers/backtrace_silencers.rb +7 -0
  54. data/test/rails_app/config/initializers/devise.rb +174 -0
  55. data/test/rails_app/config/initializers/inflections.rb +10 -0
  56. data/test/rails_app/config/initializers/mime_types.rb +5 -0
  57. data/test/rails_app/config/initializers/secret_token.rb +7 -0
  58. data/test/rails_app/config/initializers/session_store.rb +8 -0
  59. data/test/rails_app/config/locales/en.yml +5 -0
  60. data/test/rails_app/config/routes.rb +4 -0
  61. data/test/rails_app/script/rails +6 -0
  62. data/test/routes_test.rb +20 -0
  63. data/test/test_helper.rb +31 -0
  64. metadata +222 -0
@@ -0,0 +1,3 @@
1
+ module DeviseInvitable
2
+ VERSION = '0.4.rc'.freeze
3
+ end
@@ -0,0 +1,13 @@
1
+ require 'rails/generators/active_record'
2
+
3
+ module ActiveRecord
4
+ module Generators
5
+ class DeviseInvitableGenerator < ActiveRecord::Generators::Base
6
+ source_root File.expand_path("../templates", __FILE__)
7
+
8
+ def copy_devise_migration
9
+ migration_template "migration.rb", "db/migrate/devise_invitable_add_to_#{table_name}"
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,20 @@
1
+ class DeviseInvitableAddTo<%= table_name.camelize %> < ActiveRecord::Migration
2
+ def self.up
3
+ change_table :<%= table_name %> do |t|
4
+ t.string :invitation_token, :limit => 60
5
+ t.datetime :invitation_sent_at
6
+ t.index :invitation_token # for invitable
7
+ end
8
+
9
+ # And allow null encrypted_password and password_salt:
10
+ change_column_null :<%= table_name %>, :encrypted_password, true
11
+ <% if class_name.constantize.columns_hash['password_salt'] -%>
12
+ change_column_null :<%= table_name %>, :password_salt, true
13
+ <% end -%>
14
+ end
15
+
16
+ def self.down
17
+ remove_column :<%= table_name %>, :invitation_sent_at
18
+ remove_column :<%= table_name %>, :invitation_token
19
+ end
20
+ end
@@ -0,0 +1,16 @@
1
+ module DeviseInvitable
2
+ module Generators
3
+ class DeviseInvitableGenerator < Rails::Generators::NamedBase
4
+ namespace "devise_invitable"
5
+
6
+ desc "Add :invitable directive in the given model. Also generate migration for ActiveRecord"
7
+
8
+ def inject_devise_invitable_content
9
+ path = File.join("app", "models", "#{file_path}.rb")
10
+ inject_into_file(path, "invitable, :", :after => "devise :") if File.exists?(path)
11
+ end
12
+
13
+ hook_for :orm
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,35 @@
1
+ module DeviseInvitable
2
+ module Generators
3
+ class InstallGenerator < Rails::Generators::Base
4
+ source_root File.expand_path("../../templates", __FILE__)
5
+ desc "Add DeviseInvitable config variables to the Devise initializer and copy DeviseInvitable locale files to your application."
6
+
7
+ def add_config_options_to_initializer
8
+ devise_initializer_path = "config/initializers/devise.rb"
9
+ if File.exist?(devise_initializer_path)
10
+ old_content = File.read(devise_initializer_path)
11
+
12
+ if old_content.match(Regexp.new(/^\s# ==> Configuration for :invitable\n/))
13
+ false
14
+ else
15
+ inject_into_file(devise_initializer_path, :before => " # ==> Configuration for :confirmable\n") do
16
+ <<-CONTENT
17
+ # ==> Configuration for :invitable
18
+ # The period the generated invitation token is valid, after
19
+ # this period, the invited resource won't be able to accept the invitation.
20
+ # When invite_for is 0 (the default), the invitation won't expire.
21
+ # config.invite_for = 2.weeks
22
+
23
+ CONTENT
24
+ end
25
+ end
26
+ end
27
+ end
28
+
29
+ def copy_locale
30
+ copy_file "../../../config/locales/en.yml", "config/locales/devise_invitable.en.yml"
31
+ end
32
+
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,10 @@
1
+ require 'generators/devise/views_generator'
2
+
3
+ module DeviseInvitable
4
+ module Generators
5
+ class ViewsGenerator < Devise::Generators::ViewsGenerator
6
+ source_root File.expand_path("../../../../app/views", __FILE__)
7
+ desc 'Copies all DeviseInvitable views to your application.'
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,45 @@
1
+ require 'test/test_helper'
2
+ require 'rails/generators'
3
+ require 'generators/devise_invitable/devise_invitable_generator'
4
+
5
+ class GeneratorsTest < ActiveSupport::TestCase
6
+ RAILS_APP_PATH = File.expand_path("../rails_app", __FILE__)
7
+
8
+ test "rails g should include the 3 generators" do
9
+ output = `cd #{RAILS_APP_PATH} && rails g`
10
+ assert output.match(%r|DeviseInvitable:\n devise_invitable\n devise_invitable:install\n devise_invitable:views|)
11
+ end
12
+
13
+ test "rails g devise_invitable:install" do
14
+ output = `cd #{RAILS_APP_PATH} && rails g devise_invitable:install -p`
15
+ assert output.match(%r|inject.+ config/initializers/devise\.rb\n|)
16
+ assert output.match(%r|create.+ config/locales/devise_invitable\.en\.yml\n|)
17
+ end
18
+
19
+ test "rails g devise_invitable:views not scoped" do
20
+ output = `cd #{RAILS_APP_PATH} && rails g devise_invitable:views -p`
21
+ assert output.match(%r|create.+ app/views/devise\n|)
22
+ assert output.match(%r|create.+ app/views/devise/invitations/edit\.html\.erb\n|)
23
+ assert output.match(%r|create.+ app/views/devise/invitations/new\.html\.erb\n|)
24
+ assert output.match(%r|create.+ app/views/devise/mailer/invitation_instructions\.html\.erb\n|)
25
+ end
26
+
27
+ test "rails g devise_invitable:views scoped" do
28
+ output = `cd #{RAILS_APP_PATH} && rails g devise_invitable:views octopussies -p`
29
+ assert output.match(%r|create.+ app/views/octopussies\n|)
30
+ assert output.match(%r|create.+ app/views/octopussies/invitations/edit\.html\.erb\n|)
31
+ assert output.match(%r|create.+ app/views/octopussies/invitations/new\.html\.erb\n|)
32
+ assert output.match(%r|create.+ app/views/octopussies/mailer/invitation_instructions\.html\.erb\n|)
33
+ end
34
+
35
+ test "rails g devise_invitable Octopussy" do
36
+ output = `cd #{RAILS_APP_PATH} && rails g devise_invitable Octopussy -p`
37
+ assert output.match(%r|inject.+ app/models/octopussy\.rb\n|)
38
+ assert output.match(%r|invoke.+ #{DEVISE_ORM}\n|)
39
+ if DEVISE_ORM == :active_record
40
+ assert output.match(%r|create.+ db/migrate/\d{14}_devise_invitable_add_to_octopussies\.rb\n|)
41
+ elsif DEVISE_ORM == :mongoid
42
+ assert !output.match(%r|create.+ db/migrate/\d{14}_devise_invitable_add_to_octopussies\.rb\n|)
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,107 @@
1
+ require 'test/test_helper'
2
+ require 'test/integration_tests_helper'
3
+
4
+ class InvitationTest < ActionDispatch::IntegrationTest
5
+ def teardown
6
+ Capybara.reset_sessions!
7
+ end
8
+
9
+ def send_invitation(&block)
10
+ visit new_user_invitation_path
11
+
12
+ fill_in 'user_email', :with => 'user@test.com'
13
+ yield if block_given?
14
+ click_button 'Send an invitation'
15
+ end
16
+
17
+ def set_password(options={}, &block)
18
+ unless options[:visit] == false
19
+ visit accept_user_invitation_path(:invitation_token => options[:invitation_token])
20
+ end
21
+
22
+ fill_in 'user_password', :with => '987654321'
23
+ fill_in 'user_password_confirmation', :with => '987654321'
24
+ yield if block_given?
25
+ click_button 'Set my password'
26
+ end
27
+
28
+ test 'not authenticated user should not be able to send an invitation' do
29
+ get new_user_invitation_path
30
+ assert_redirected_to new_user_session_path
31
+ end
32
+
33
+ test 'authenticated user should be able to send an invitation' do
34
+ sign_in_as_user
35
+
36
+ send_invitation
37
+ assert_equal root_path, current_path
38
+ assert page.has_css?('p#notice', :text => 'An invitation email has been sent to user@test.com.')
39
+ end
40
+
41
+ test 'authenticated user with invalid email should receive an error message' do
42
+ user = create_full_user
43
+ sign_in_as_user(user)
44
+ send_invitation do
45
+ fill_in 'user_email', :with => user.email
46
+ end
47
+
48
+ assert_equal user_invitation_path, current_path
49
+ assert page.has_css?("input[type=text][value='#{user.email}']")
50
+ assert page.has_css?('#error_explanation li', :text => 'Email has already been taken')
51
+ end
52
+
53
+ test 'authenticated user should not be able to visit edit invitation page' do
54
+ sign_in_as_user
55
+
56
+ visit accept_user_invitation_path
57
+
58
+ assert_equal root_path, current_path
59
+ end
60
+
61
+ test 'not authenticated user with invalid invitation token should not be able to set his password' do
62
+ user = create_user
63
+ visit accept_user_invitation_path(:invitation_token => 'invalid_token')
64
+
65
+ assert_equal root_path, current_path
66
+ assert page.has_css?('p#alert', :text => 'The invitation token provided is not valid!')
67
+ end
68
+
69
+ test 'not authenticated user with valid invitation token but invalid password should not be able to set his password' do
70
+ user = create_user(false)
71
+ set_password :invitation_token => user.invitation_token do
72
+ fill_in 'Password confirmation', :with => 'other_password'
73
+ end
74
+ assert_equal user_invitation_path, current_path
75
+ assert page.has_css?('#error_explanation li', :text => 'Password doesn\'t match confirmation')
76
+ assert_nil user.encrypted_password
77
+ end
78
+
79
+ test 'not authenticated user with valid data should be able to change his password' do
80
+ user = create_user(false)
81
+ set_password :invitation_token => user.invitation_token
82
+
83
+ assert_equal root_path, current_path
84
+ assert page.has_css?('p#notice', :text => 'Your password was set successfully. You are now signed in.')
85
+ assert user.reload.valid_password?('987654321')
86
+ end
87
+
88
+ test 'after entering invalid data user should still be able to set his password' do
89
+ user = create_user(false)
90
+ set_password :invitation_token => user.invitation_token do
91
+ fill_in 'Password confirmation', :with => 'other_password'
92
+ end
93
+ assert_equal user_invitation_path, current_path
94
+ assert page.has_css?('#error_explanation')
95
+ assert_nil user.encrypted_password
96
+
97
+ set_password :visit => false
98
+ assert page.has_css?('p#notice', :text => 'Your password was set successfully. You are now signed in.')
99
+ assert user.reload.valid_password?('987654321')
100
+ end
101
+
102
+ test 'sign in user automatically after setting it\'s password' do
103
+ user = create_user(false)
104
+ set_password :invitation_token => user.invitation_token
105
+ assert_equal root_path, current_path
106
+ end
107
+ end
@@ -0,0 +1,58 @@
1
+ class ActionController::IntegrationTest
2
+
3
+ def warden
4
+ request.env['warden']
5
+ end
6
+
7
+ def create_full_user
8
+ @user ||= begin
9
+ user = User.create!(
10
+ :username => 'usertest',
11
+ :email => 'fulluser@test.com',
12
+ :password => '123456',
13
+ :password_confirmation => '123456',
14
+ :created_at => Time.now.utc
15
+ )
16
+ user.confirm!
17
+ user
18
+ end
19
+ end
20
+
21
+ def sign_in_as_user(user = nil)
22
+ user ||= create_full_user
23
+ visit new_user_session_path
24
+ fill_in 'user_email', :with => user.email
25
+ fill_in 'user_password', :with => '123456'
26
+ fill_in 'user_password', :with => user.password
27
+ click_button 'Sign in'
28
+ end
29
+
30
+ def create_user(accept_invitation = true)
31
+ user = User.new :email => 'newuser@test.com'
32
+ user.skip_confirmation!
33
+ user.invitation_token = 'token'
34
+ user.invitation_sent_at = Time.now.utc
35
+ user.save(:validate => false)
36
+ user.accept_invitation! if accept_invitation
37
+ user
38
+ end
39
+
40
+ # Fix assert_redirect_to in integration sessions because they don't take into
41
+ # account Middleware redirects.
42
+ #
43
+ def assert_redirected_to(url)
44
+ assert [301, 302].include?(@integration_session.status),
45
+ "Expected status to be 301 or 302, got #{@integration_session.status}"
46
+
47
+ url = prepend_host(url)
48
+ location = prepend_host(@integration_session.headers["Location"])
49
+ assert_equal url, location
50
+ end
51
+
52
+ protected
53
+
54
+ def prepend_host(url)
55
+ url = "http://#{request.host}#{url}" if url[0] == ?/
56
+ url
57
+ end
58
+ end
@@ -0,0 +1,63 @@
1
+ require 'test/test_helper'
2
+ require 'test/model_tests_helper'
3
+
4
+ class InvitationMailTest < ActionMailer::TestCase
5
+
6
+ def setup
7
+ setup_mailer
8
+ Devise.mailer_sender = 'test@example.com'
9
+ end
10
+
11
+ def user
12
+ @user ||= begin
13
+ user = create_user_with_invitation('token')
14
+ user.invite!
15
+ user
16
+ end
17
+ end
18
+
19
+ def mail
20
+ @mail ||= begin
21
+ user
22
+ ActionMailer::Base.deliveries.last
23
+ end
24
+ end
25
+
26
+ test 'email sent after reseting the user password' do
27
+ assert_not_nil mail
28
+ end
29
+
30
+ test 'content type should be set to html' do
31
+ assert_equal 'text/html; charset=UTF-8', mail.content_type
32
+ end
33
+
34
+ test 'send invitation to the user email' do
35
+ assert_equal [user.email], mail.to
36
+ end
37
+
38
+ test 'setup sender from configuration' do
39
+ assert_equal ['test@example.com'], mail.from
40
+ end
41
+
42
+ test 'setup subject from I18n' do
43
+ store_translations :en, :devise => { :mailer => { :invitation_instructions => { :subject => 'Localized Invitation' } } } do
44
+ assert_equal 'Localized Invitation', mail.subject
45
+ end
46
+ end
47
+
48
+ test 'subject namespaced by model' do
49
+ store_translations :en, :devise => { :mailer => { :invitation_instructions => { :user_subject => 'User Invitation' } } } do
50
+ assert_equal 'User Invitation', mail.subject
51
+ end
52
+ end
53
+
54
+ test 'body should have user info' do
55
+ assert_match /#{user.email}/, mail.body
56
+ end
57
+
58
+ test 'body should have link to confirm the account' do
59
+ host = ActionMailer::Base.default_url_options[:host]
60
+ invitation_url_regexp = %r{<a href=\"http://#{host}/users/invitation/accept\?invitation_token=#{user.invitation_token}">}
61
+ assert_match invitation_url_regexp, mail.body
62
+ end
63
+ end
@@ -0,0 +1,41 @@
1
+ class ActiveSupport::TestCase
2
+ def setup_mailer
3
+ ActionMailer::Base.deliveries = []
4
+ end
5
+
6
+ def store_translations(locale, translations, &block)
7
+ begin
8
+ I18n.backend.store_translations locale, translations
9
+ yield
10
+ ensure
11
+ I18n.reload!
12
+ end
13
+ end
14
+
15
+ # Helpers for creating new users
16
+ #
17
+ def generate_unique_email
18
+ @@email_count ||= 0
19
+ @@email_count += 1
20
+ "test#{@@email_count}@email.com"
21
+ end
22
+
23
+ def valid_attributes(attributes={})
24
+ { :email => generate_unique_email,
25
+ :password => '123456',
26
+ :password_confirmation => '123456' }.update(attributes)
27
+ end
28
+
29
+ def new_user(attributes={})
30
+ User.new(valid_attributes(attributes))
31
+ end
32
+
33
+ def create_user_with_invitation(invitation_token, attributes={})
34
+ user = new_user({:password => nil, :password_confirmation => nil}.update(attributes))
35
+ user.skip_confirmation!
36
+ user.invitation_token = invitation_token
37
+ user.invitation_sent_at = Time.now.utc
38
+ user.save(:validate => false)
39
+ user
40
+ end
41
+ end
@@ -0,0 +1,213 @@
1
+ require 'test/test_helper'
2
+ require 'test/model_tests_helper'
3
+
4
+ class InvitableTest < ActiveSupport::TestCase
5
+
6
+ def setup
7
+ setup_mailer
8
+ end
9
+
10
+ test 'should not generate invitation token after creating a record' do
11
+ assert_nil new_user.invitation_token
12
+ end
13
+
14
+ test 'should not regenerate invitation token each time' do
15
+ user = new_user
16
+ user.invite!
17
+ token = user.invitation_token
18
+ assert_not_nil user.invitation_token
19
+ assert_not_nil user.invitation_sent_at
20
+ 3.times do
21
+ user.invite!
22
+ assert_equal token, user.invitation_token
23
+ end
24
+ end
25
+
26
+ test 'should set invitation sent at each time' do
27
+ user = new_user
28
+ user.invite!
29
+ old_invitation_sent_at = 3.days.ago
30
+ user.update_attribute :invitation_sent_at, old_invitation_sent_at
31
+ 3.times do
32
+ user.invite!
33
+ assert_not_equal old_invitation_sent_at, user.invitation_sent_at
34
+ user.update_attribute :invitation_sent_at, old_invitation_sent_at
35
+ end
36
+ end
37
+
38
+ test 'should not regenerate invitation token even after the invitation token is not valid' do
39
+ User.invite_for = 1.day
40
+ user = new_user
41
+ user.invite!
42
+ token = user.invitation_token
43
+ user.invitation_sent_at = 3.days.ago
44
+ user.save
45
+ user.invite!
46
+ assert_equal token, user.invitation_token
47
+ end
48
+
49
+ test 'should test invitation sent at with invite_for configuration value' do
50
+ user = create_user_with_invitation('token')
51
+
52
+ User.stubs(:invite_for).returns(nil)
53
+ user.invitation_sent_at = Time.now.utc
54
+ assert user.valid_invitation?
55
+
56
+ User.stubs(:invite_for).returns(nil)
57
+ user.invitation_sent_at = 1.year.ago
58
+ assert user.valid_invitation?
59
+
60
+ User.stubs(:invite_for).returns(0)
61
+ user.invitation_sent_at = Time.now.utc
62
+ assert user.valid_invitation?
63
+
64
+ User.stubs(:invite_for).returns(0)
65
+ user.invitation_sent_at = 1.day.ago
66
+ assert user.valid_invitation?
67
+
68
+ User.stubs(:invite_for).returns(1.day)
69
+ user.invitation_sent_at = Time.now.utc
70
+ assert user.valid_invitation?
71
+
72
+ User.stubs(:invite_for).returns(1.day)
73
+ user.invitation_sent_at = 1.day.ago
74
+ assert !user.valid_invitation?
75
+ end
76
+
77
+ test 'should never generate the same invitation token for different users' do
78
+ invitation_tokens = []
79
+ 3.times do
80
+ user = new_user
81
+ user.invite!
82
+ token = user.invitation_token
83
+ assert !invitation_tokens.include?(token)
84
+ invitation_tokens << token
85
+ end
86
+ end
87
+
88
+ test 'should set password and password confirmation from params' do
89
+ create_user_with_invitation('valid_token', :password => nil, :password_confirmation => nil)
90
+ user = User.accept_invitation!(:invitation_token => 'valid_token', :password => '123456789', :password_confirmation => '123456789')
91
+ assert user.valid_password?('123456789')
92
+ end
93
+
94
+ test 'should set password and save the record' do
95
+ user = create_user_with_invitation('valid_token', :password => nil, :password_confirmation => nil)
96
+ old_encrypted_password = user.encrypted_password
97
+ user = User.accept_invitation!(:invitation_token => 'valid_token', :password => '123456789', :password_confirmation => '123456789')
98
+ assert_not_equal old_encrypted_password, user.encrypted_password
99
+ end
100
+
101
+ test 'should clear invitation token while setting the password' do
102
+ user = new_user
103
+ user.skip_confirmation!
104
+ user.update_attribute(:invitation_token, 'valid_token')
105
+ assert_present user.invitation_token
106
+ assert user.accept_invitation!
107
+ assert_nil user.invitation_token
108
+ end
109
+
110
+ test 'should not clear invitation token if record is invalid' do
111
+ user = new_user
112
+ user.skip_confirmation!
113
+ user.update_attribute(:invitation_token, 'valid_token')
114
+ assert_present user.invitation_token
115
+ User.accept_invitation!(:invitation_token => 'valid_token', :password => '123456789', :password_confirmation => '987654321')
116
+ user.reload
117
+ assert_present user.invitation_token
118
+ end
119
+
120
+ test 'should reset invitation token and send invitation by email' do
121
+ user = new_user
122
+ assert_difference('ActionMailer::Base.deliveries.size') do
123
+ token = user.invitation_token
124
+ user.invite!
125
+ assert_not_equal token, user.invitation_token
126
+ end
127
+ end
128
+
129
+ test 'should return a record with invitation token and no errors to send invitation by email' do
130
+ invited_user = User.invite!(:email => "valid@email.com")
131
+ assert invited_user.errors.blank?
132
+ assert_present invited_user.invitation_token
133
+ assert_equal 'valid@email.com', invited_user.email
134
+ assert invited_user.persisted?
135
+ end
136
+
137
+ test 'should set all attributes with no errors' do
138
+ invited_user = User.invite!(:email => "valid@email.com", :username => 'first name')
139
+ assert invited_user.errors.blank?
140
+ assert_equal 'first name', invited_user.username
141
+ assert invited_user.persisted?
142
+ end
143
+
144
+ test 'should return a record with errors if user was found by e-mail' do
145
+ user = create_user_with_invitation('')
146
+ user.update_attribute(:invitation_token, nil)
147
+ invited_user = User.invite!(:email => user.email)
148
+ assert_equal invited_user, user
149
+ assert_equal ['has already been taken'], invited_user.errors[:email]
150
+ end
151
+
152
+ test 'should return a new record with errors if e-mail is blank' do
153
+ invited_user = User.invite!(:email => '')
154
+ assert invited_user.new_record?
155
+ assert_equal ["can't be blank"], invited_user.errors[:email]
156
+ end
157
+
158
+ test 'should return a new record with errors if e-mail is invalid' do
159
+ invited_user = User.invite!(:email => 'invalid_email')
160
+ assert invited_user.new_record?
161
+ assert_equal ["is invalid"], invited_user.errors[:email]
162
+ end
163
+
164
+ test 'should set all attributes with errors if e-mail is invalid' do
165
+ invited_user = User.invite!(:email => "invalid_email.com", :username => 'first name')
166
+ assert invited_user.new_record?
167
+ assert_equal 'first name', invited_user.username
168
+ assert invited_user.errors.present?
169
+ end
170
+
171
+ test 'should find a user to set his password based on invitation_token' do
172
+ user = new_user
173
+ user.invite!
174
+
175
+ invited_user = User.accept_invitation!(:invitation_token => user.invitation_token)
176
+ assert_equal invited_user, user
177
+ end
178
+
179
+ test 'should return a new record with errors if no invitation_token is found' do
180
+ invited_user = User.accept_invitation!(:invitation_token => 'invalid_token')
181
+ assert invited_user.new_record?
182
+ assert_equal ['is invalid'], invited_user.errors[:invitation_token]
183
+ end
184
+
185
+ test 'should return a new record with errors if invitation_token is blank' do
186
+ invited_user = User.accept_invitation!(:invitation_token => '')
187
+ assert invited_user.new_record?
188
+ assert_equal ["can't be blank"], invited_user.errors[:invitation_token]
189
+ end
190
+
191
+ test 'should return record with errors if invitation_token has expired' do
192
+ user = create_user_with_invitation('valid_token')
193
+ user.update_attribute(:invitation_sent_at, 1.day.ago)
194
+ User.stubs(:invite_for).returns(10.hours)
195
+ invited_user = User.accept_invitation!(:invitation_token => 'valid_token')
196
+ assert_equal user, invited_user
197
+ assert_equal ["is invalid"], invited_user.errors[:invitation_token]
198
+ end
199
+
200
+ test 'should set successfully user password given the new password and confirmation' do
201
+ user = new_user(:password => nil, :password_confirmation => nil)
202
+ user.invite!
203
+
204
+ invited_user = User.accept_invitation!(
205
+ :invitation_token => user.invitation_token,
206
+ :password => 'new_password',
207
+ :password_confirmation => 'new_password'
208
+ )
209
+ user.reload
210
+
211
+ assert user.valid_password?('new_password')
212
+ end
213
+ end