revise 0.0.1
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.
- data/lib/padrino/revise.rb +8 -0
- data/lib/revise.rb +110 -0
- data/lib/revise/controllers/accounts.rb +59 -0
- data/lib/revise/controllers/confirmations.rb +26 -0
- data/lib/revise/controllers/invitations.rb +55 -0
- data/lib/revise/controllers/main.rb +13 -0
- data/lib/revise/controllers/recovery.rb +60 -0
- data/lib/revise/controllers/sessions.rb +22 -0
- data/lib/revise/core_ext/module.rb +52 -0
- data/lib/revise/core_ext/string.rb +14 -0
- data/lib/revise/helpers/authentication.rb +21 -0
- data/lib/revise/helpers/core.rb +48 -0
- data/lib/revise/inviter.rb +40 -0
- data/lib/revise/locale/en.yml +11 -0
- data/lib/revise/mailers/confirmable.rb +18 -0
- data/lib/revise/mailers/invitable.rb +18 -0
- data/lib/revise/mailers/recoverable.rb +18 -0
- data/lib/revise/models.rb +99 -0
- data/lib/revise/models/authenticatable.rb +137 -0
- data/lib/revise/models/confirmable.rb +236 -0
- data/lib/revise/models/database_authenticatable.rb +107 -0
- data/lib/revise/models/invitable.rb +237 -0
- data/lib/revise/models/recoverable.rb +99 -0
- data/lib/revise/orm/mongo_mapper.rb +2 -0
- data/lib/revise/param_filter.rb +41 -0
- data/test/controllers/accounts_test.rb +148 -0
- data/test/controllers/invitations_test.rb +105 -0
- data/test/controllers/sessions_test.rb +35 -0
- data/test/factories/account.rb +15 -0
- data/test/models/account_test.rb +45 -0
- data/test/models/invitation_test.rb +423 -0
- data/test/test.rake +13 -0
- data/test/test_config.rb +23 -0
- metadata +181 -0
@@ -0,0 +1,148 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../test_config.rb')
|
2
|
+
|
3
|
+
describe 'Accounts Controller' do
|
4
|
+
setup do
|
5
|
+
header 'Accept', 'text/html'
|
6
|
+
|
7
|
+
account = FactoryGirl.create(:account)
|
8
|
+
post '/sessions', {:email => account.email, :bypass => true}
|
9
|
+
assert last_response.status == 302
|
10
|
+
end
|
11
|
+
|
12
|
+
teardown do
|
13
|
+
delete '/sessions'
|
14
|
+
assert last_response.status == 302
|
15
|
+
end
|
16
|
+
|
17
|
+
should 'return a new page' do
|
18
|
+
delete '/sessions'
|
19
|
+
assert last_response.status == 302
|
20
|
+
|
21
|
+
get '/accounts/new'
|
22
|
+
assert last_response.status == 200
|
23
|
+
end
|
24
|
+
|
25
|
+
should 'create a new account' do
|
26
|
+
delete '/sessions'
|
27
|
+
assert last_response.status == 302
|
28
|
+
|
29
|
+
name = Faker::Lorem.words(2)
|
30
|
+
account_params = {:first_name => name[0],
|
31
|
+
:last_name => name[1],
|
32
|
+
:email => "#{Faker::Internet.user_name}_#{rand(0...1000)}@example.org",
|
33
|
+
:password => 'testpass',
|
34
|
+
:password_confirmation => 'testpass'}
|
35
|
+
|
36
|
+
post '/accounts', {:account => account_params}
|
37
|
+
assert last_response.status == 302
|
38
|
+
|
39
|
+
account = Account.first(:first_name => name[0])
|
40
|
+
assert account
|
41
|
+
end
|
42
|
+
|
43
|
+
should 'return an edit page' do
|
44
|
+
get '/accounts/edit'
|
45
|
+
assert last_response.status == 200
|
46
|
+
end
|
47
|
+
|
48
|
+
should 'update an account' do
|
49
|
+
delete '/sessions'
|
50
|
+
assert last_response.status == 302
|
51
|
+
|
52
|
+
account = FactoryGirl.create(:account)
|
53
|
+
|
54
|
+
post '/sessions', {:email => account.email, :bypass => true}
|
55
|
+
assert last_response.status == 302
|
56
|
+
|
57
|
+
put '/accounts', {:account => {:last_name => 'Johnson'}}
|
58
|
+
assert last_response.status == 302
|
59
|
+
|
60
|
+
account = Account.find_by_id(account.id)
|
61
|
+
assert account.last_name == 'Johnson'
|
62
|
+
end
|
63
|
+
|
64
|
+
should 'delete an account' do
|
65
|
+
delete '/sessions'
|
66
|
+
assert last_response.status == 302
|
67
|
+
|
68
|
+
account = FactoryGirl.create(:account)
|
69
|
+
post '/sessions', {:email => account.email, :bypass => true}
|
70
|
+
assert last_response.status == 302
|
71
|
+
|
72
|
+
delete '/accounts'
|
73
|
+
assert last_response.status == 302
|
74
|
+
|
75
|
+
assert Account.find_by_id(account.id).nil?
|
76
|
+
end
|
77
|
+
|
78
|
+
should 'confirm an account' do
|
79
|
+
delete '/accounts'
|
80
|
+
assert last_response.status == 302
|
81
|
+
|
82
|
+
account = FactoryGirl.create(:account, :confirmed_at => nil)
|
83
|
+
|
84
|
+
post '/sessions', {:email => account.email, :bypass => true}
|
85
|
+
assert last_response.status == 302
|
86
|
+
|
87
|
+
get "/accounts/confirm/#{account.confirmation_token}"
|
88
|
+
assert last_response.status == 200
|
89
|
+
|
90
|
+
account = Account.find_by_id(account.id)
|
91
|
+
assert account.confirmed?
|
92
|
+
end
|
93
|
+
|
94
|
+
should 'return a forgot_pass page' do
|
95
|
+
delete '/sessions'
|
96
|
+
assert last_response.status == 302
|
97
|
+
|
98
|
+
get '/accounts/forgot-password'
|
99
|
+
assert last_response.status == 200
|
100
|
+
end
|
101
|
+
|
102
|
+
should 'reset a password' do
|
103
|
+
delete '/sessions'
|
104
|
+
assert last_response.status == 302
|
105
|
+
|
106
|
+
account = FactoryGirl.create(:account)
|
107
|
+
|
108
|
+
post '/accounts/forgot-password', {:email => account.email}
|
109
|
+
assert last_response.status == 302
|
110
|
+
|
111
|
+
account = Account.find_by_id(account.id)
|
112
|
+
assert account.reset_password_token
|
113
|
+
|
114
|
+
get "/accounts/reset-password/#{account.reset_password_token}"
|
115
|
+
assert last_response.status == 200
|
116
|
+
|
117
|
+
put "/accounts/reset-password/#{account.reset_password_token}", {:password => 'resetpass', :password_confirmation => 'resetpass'}
|
118
|
+
assert last_response.status == 302
|
119
|
+
|
120
|
+
old_pass_crypt = account.encrypted_password
|
121
|
+
account = Account.find_by_id(account.id)
|
122
|
+
assert account.encrypted_password != old_pass_crypt
|
123
|
+
end
|
124
|
+
|
125
|
+
should 'refuse to return an edit page' do
|
126
|
+
delete '/sessions'
|
127
|
+
assert last_response.status == 302
|
128
|
+
|
129
|
+
get '/accounts/edit'
|
130
|
+
assert last_response.status == 403
|
131
|
+
end
|
132
|
+
|
133
|
+
should 'refuse to update' do
|
134
|
+
delete '/sessions'
|
135
|
+
assert last_response.status == 302
|
136
|
+
|
137
|
+
put '/accounts'
|
138
|
+
assert last_response.status == 403
|
139
|
+
end
|
140
|
+
|
141
|
+
should 'refuse to delete an account' do
|
142
|
+
delete '/sessions'
|
143
|
+
assert last_response.status == 302
|
144
|
+
|
145
|
+
delete '/accounts'
|
146
|
+
assert last_response.status == 403
|
147
|
+
end
|
148
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../test_config.rb')
|
2
|
+
|
3
|
+
describe 'Accounts Controller' do
|
4
|
+
def sign_in(account=nil)
|
5
|
+
account ||= FactoryGirl.create(:account)
|
6
|
+
|
7
|
+
delete '/sessions'
|
8
|
+
assert last_response.status == 302
|
9
|
+
|
10
|
+
post '/sessions', {:email => account.email, :bypass => true}
|
11
|
+
assert last_response.status == 302
|
12
|
+
end
|
13
|
+
|
14
|
+
def send_invitation(email="#{Faker::Internet.user_name}_#{rand(0...1000)}@example.org")
|
15
|
+
post '/invitations', {:account => { :email => email}}
|
16
|
+
end
|
17
|
+
|
18
|
+
setup do
|
19
|
+
header 'Accept', 'text/html'
|
20
|
+
sign_in
|
21
|
+
end
|
22
|
+
|
23
|
+
teardown do
|
24
|
+
delete '/sessions'
|
25
|
+
assert last_response.status == 302
|
26
|
+
end
|
27
|
+
|
28
|
+
should 'not allow a non-authenticated account to send an invitation' do
|
29
|
+
delete '/sessions'
|
30
|
+
|
31
|
+
get '/invitations/new'
|
32
|
+
assert last_response.status == 403
|
33
|
+
end
|
34
|
+
|
35
|
+
should 'let an authenticated account send an invitation' do
|
36
|
+
email = "#{Faker::Internet.user_name}_#{rand(0...1000)}@example.org"
|
37
|
+
send_invitation(email)
|
38
|
+
assert last_response.status == 302
|
39
|
+
|
40
|
+
account = Account.find_by_email(email)
|
41
|
+
assert !account.invitation_token.nil?
|
42
|
+
end
|
43
|
+
|
44
|
+
should 'not allow a user with no invites left to send an invitation' do
|
45
|
+
account = FactoryGirl.build(:account)
|
46
|
+
account.invitation_limit = 0
|
47
|
+
account.save
|
48
|
+
sign_in(account)
|
49
|
+
|
50
|
+
email = "#{Faker::Internet.user_name}_#{rand(0...1000)}@example.org"
|
51
|
+
send_invitation(email)
|
52
|
+
assert last_response.status == 403
|
53
|
+
end
|
54
|
+
|
55
|
+
should 'default a user with nil invitation_limit to Account.invitation_limit' do
|
56
|
+
Account.stubs(:invitation_limit).returns(3)
|
57
|
+
|
58
|
+
account = FactoryGirl.create(:account)
|
59
|
+
assert account[:invitation_limit].nil?
|
60
|
+
assert_equal 3, account.invitation_limit
|
61
|
+
sign_in(account)
|
62
|
+
|
63
|
+
send_invitation()
|
64
|
+
|
65
|
+
account.reload
|
66
|
+
assert_equal 2, account.invitation_limit
|
67
|
+
end
|
68
|
+
|
69
|
+
should 'not decrement invitation limit when trying to invite again a user which is invited' do
|
70
|
+
Account.stubs(:invitation_limit).returns(3)
|
71
|
+
|
72
|
+
account = FactoryGirl.create(:account)
|
73
|
+
assert account[:invitation_limit].nil?
|
74
|
+
assert_equal 3, account.invitation_limit
|
75
|
+
sign_in(account)
|
76
|
+
|
77
|
+
send_invitation()
|
78
|
+
account.reload
|
79
|
+
assert_equal 2, account.invitation_limit
|
80
|
+
|
81
|
+
send_invitation()
|
82
|
+
account.reload
|
83
|
+
assert_equal 1, account.invitation_limit
|
84
|
+
end
|
85
|
+
|
86
|
+
should 'set invited_by when user invites someone' do
|
87
|
+
account = FactoryGirl.create(:account)
|
88
|
+
sign_in(account)
|
89
|
+
|
90
|
+
email = "#{Faker::Internet.user_name}_#{rand(0...1000)}@example.org"
|
91
|
+
send_invitation(email)
|
92
|
+
|
93
|
+
invited_account = Account.find_by_email(email)
|
94
|
+
assert !invited_account.nil?
|
95
|
+
assert_equal account, invited_account.invited_by
|
96
|
+
end
|
97
|
+
|
98
|
+
should 'allow admin to send invitations anyway' do
|
99
|
+
admin_account = FactoryGirl.create(:account_admin, :invitation_limit => 0)
|
100
|
+
sign_in(admin_account)
|
101
|
+
|
102
|
+
send_invitation
|
103
|
+
assert last_response.status == 302
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../test_config.rb')
|
2
|
+
|
3
|
+
describe 'Sessions Controller' do
|
4
|
+
setup do
|
5
|
+
header 'Accept', 'text/html'
|
6
|
+
end
|
7
|
+
|
8
|
+
should 'respond with a new page' do
|
9
|
+
get '/sessions/new'
|
10
|
+
assert last_response.status == 200
|
11
|
+
end
|
12
|
+
|
13
|
+
should 'create a new session and then destroy it' do
|
14
|
+
account = FactoryGirl.create(:account)
|
15
|
+
|
16
|
+
post '/sessions', {:email => account.email, :bypass => true}
|
17
|
+
assert last_response.status == 302
|
18
|
+
|
19
|
+
delete '/sessions'
|
20
|
+
assert last_response.status == 302
|
21
|
+
|
22
|
+
get '/accounts/edit'
|
23
|
+
assert last_response.status == 403
|
24
|
+
end
|
25
|
+
|
26
|
+
should 'refuse to create a session' do
|
27
|
+
account = FactoryGirl.create(:account)
|
28
|
+
|
29
|
+
post '/sessions'
|
30
|
+
assert last_response.status == 302
|
31
|
+
|
32
|
+
get '/accounts/edit'
|
33
|
+
assert last_response.status == 403
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
FactoryGirl.define do
|
2
|
+
factory :account do
|
3
|
+
email { "#{Faker::Internet.user_name}_#{rand(0...1000)}@example.org" }
|
4
|
+
username { Faker::Internet.user_name + "_#{rand(0...1000)}" }
|
5
|
+
password 'testpass'
|
6
|
+
password_confirmation 'testpass'
|
7
|
+
name { Faker::Name.name }
|
8
|
+
skip_email true
|
9
|
+
role :test
|
10
|
+
end
|
11
|
+
|
12
|
+
factory :account_admin, :parent => :account do
|
13
|
+
role :admin
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../test_config.rb')
|
2
|
+
|
3
|
+
describe 'Account Model' do
|
4
|
+
should 'save an account model instance' do
|
5
|
+
account = FactoryGirl.build(:account)
|
6
|
+
assert account.save
|
7
|
+
|
8
|
+
assert account.encrypted_password
|
9
|
+
end
|
10
|
+
|
11
|
+
should 'destroy an account' do
|
12
|
+
account = FactoryGirl.create(:account)
|
13
|
+
assert account.destroy
|
14
|
+
end
|
15
|
+
|
16
|
+
should 'update an account' do
|
17
|
+
account = FactoryGirl.create(:account)
|
18
|
+
assert account.update_attributes!(:name => 'Updated, Guy')
|
19
|
+
|
20
|
+
account = Account.find_by_id(account.id)
|
21
|
+
assert account.first_name == 'Updated'
|
22
|
+
end
|
23
|
+
|
24
|
+
should 'confirm an account' do
|
25
|
+
account = FactoryGirl.create(:account)
|
26
|
+
|
27
|
+
assert !account.confirmed?
|
28
|
+
|
29
|
+
account = Account.confirm_by_token(account.confirmation_token)
|
30
|
+
assert account
|
31
|
+
assert_empty account.errors
|
32
|
+
end
|
33
|
+
|
34
|
+
should 'reset a password' do
|
35
|
+
account = FactoryGirl.create(:account)
|
36
|
+
account.send_reset_password_instructions
|
37
|
+
|
38
|
+
account = Account.reset_password_by_token({:password => 'newpass',
|
39
|
+
:password_confirmation => 'newpass',
|
40
|
+
:reset_password_token => account.reset_password_token})
|
41
|
+
|
42
|
+
assert account
|
43
|
+
assert_empty account.errors
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,423 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../test_config.rb')
|
2
|
+
|
3
|
+
describe 'Account Model' do
|
4
|
+
should 'not generate invitation token after creating a record' do
|
5
|
+
account = FactoryGirl.create(:account)
|
6
|
+
assert account.invitation_token.nil?
|
7
|
+
end
|
8
|
+
|
9
|
+
should 'not regenerate invitation token each time' do
|
10
|
+
account = FactoryGirl.create(:account)
|
11
|
+
account.invite!
|
12
|
+
|
13
|
+
token = account.invitation_token
|
14
|
+
assert !account.invitation_token.nil?
|
15
|
+
assert !account.invitation_sent_at.nil?
|
16
|
+
|
17
|
+
3.times do
|
18
|
+
account.invite!
|
19
|
+
assert_equal token, account.invitation_token
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
should 'set invitation sent at each time' do
|
24
|
+
account = FactoryGirl.create(:account)
|
25
|
+
account.invite!
|
26
|
+
|
27
|
+
old_invitation_sent_at = 3.days.ago
|
28
|
+
account.update_attributes!(:invitation_sent_at => old_invitation_sent_at)
|
29
|
+
|
30
|
+
3.times do
|
31
|
+
account.invite!
|
32
|
+
assert old_invitation_sent_at != account.invitation_sent_at
|
33
|
+
account.update_attributes!(:invitation_sent_at => old_invitation_sent_at)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
should 'not regenerate invitation token even after the invitation token is not valid' do
|
38
|
+
account = FactoryGirl.create(:account)
|
39
|
+
account.invite!
|
40
|
+
|
41
|
+
token = account.invitation_token
|
42
|
+
account.invitation_sent_at = 3.days.ago
|
43
|
+
account.save
|
44
|
+
account.invite!
|
45
|
+
|
46
|
+
assert token == account.invitation_token
|
47
|
+
end
|
48
|
+
|
49
|
+
should 'test invitation sent at with invite_for configuration value' do
|
50
|
+
account = Account.invite!(:email => "#{Faker::Internet.user_name}_#{rand(0...1000)}@example.org", :skip_email => true)
|
51
|
+
|
52
|
+
Account.stubs(:invite_for).returns(nil)
|
53
|
+
account.invitation_sent_at = Time.now.utc
|
54
|
+
assert account.valid_invitation?
|
55
|
+
|
56
|
+
Account.stubs(:invite_for).returns(nil)
|
57
|
+
account.invitation_sent_at = 1.year.ago
|
58
|
+
assert account.valid_invitation?
|
59
|
+
|
60
|
+
Account.stubs(:invite_for).returns(0)
|
61
|
+
account.invitation_sent_at = Time.now.utc
|
62
|
+
assert account.valid_invitation?
|
63
|
+
|
64
|
+
Account.stubs(:invite_for).returns(0)
|
65
|
+
account.invitation_sent_at = 1.day.ago
|
66
|
+
assert account.valid_invitation?
|
67
|
+
|
68
|
+
Account.stubs(:invite_for).returns(1.day)
|
69
|
+
account.invitation_sent_at = Time.now.utc
|
70
|
+
assert account.valid_invitation?
|
71
|
+
|
72
|
+
Account.stubs(:invite_for).returns(1.day)
|
73
|
+
account.invitation_sent_at = 2.days.ago
|
74
|
+
assert !account.valid_invitation?
|
75
|
+
end
|
76
|
+
|
77
|
+
should 'never generate the same invitation token for different users' do
|
78
|
+
invitation_tokens = []
|
79
|
+
3.times do
|
80
|
+
account = FactoryGirl.create(:account)
|
81
|
+
account.invite!
|
82
|
+
token = account.invitation_token
|
83
|
+
assert !invitation_tokens.include?(token)
|
84
|
+
invitation_tokens << token
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
should 'invite with multiple columns for invite key' do
|
89
|
+
Account.stubs(:invite_key).returns(:email => Revise.email_regexp, :username => /\A.+\z/)
|
90
|
+
|
91
|
+
account = Account.invite!(:email => "#{Faker::Internet.user_name}_#{rand(0...1000)}@example.org",
|
92
|
+
:username => Faker::Internet.user_name,
|
93
|
+
:skip_email => true)
|
94
|
+
assert account.persisted?
|
95
|
+
assert account.errors.empty?
|
96
|
+
end
|
97
|
+
|
98
|
+
should 'not invite with some missing columns when invite key is an array' do
|
99
|
+
Account.stubs(:invite_key).returns(:email => Revise.email_regexp, :username => /\A.+\z/)
|
100
|
+
account = Account.invite!(:email => "#{Faker::Internet.user_name}_#{rand(0...1000)}@example.org", :skip_email => true)
|
101
|
+
assert account.new_record?
|
102
|
+
assert account.errors.present?
|
103
|
+
end
|
104
|
+
|
105
|
+
should 'disallow login when invited' do
|
106
|
+
invited_account = Account.invite!(:email => "#{Faker::Internet.user_name}_#{rand(0...1000)}@example.org", :skip_email => true)
|
107
|
+
assert !invited_account.valid_password?('1234')
|
108
|
+
end
|
109
|
+
|
110
|
+
should 'set password and password confirmation from params' do
|
111
|
+
invited_account = Account.invite!(:email => "#{Faker::Internet.user_name}_#{rand(0...1000)}@example.org", :skip_email => true)
|
112
|
+
account = Account.accept_invitation!(:invitation_token => invited_account.invitation_token,
|
113
|
+
:password => 'testpass',
|
114
|
+
:password_confirmation => 'testpass')
|
115
|
+
assert account.valid_password?('testpass')
|
116
|
+
end
|
117
|
+
|
118
|
+
should 'set password and save the record' do
|
119
|
+
account = Account.invite!(:email => "#{Faker::Internet.user_name}_#{rand(0...1000)}@example.org", :skip_email => true)
|
120
|
+
|
121
|
+
old_encrypted_password = account.encrypted_password
|
122
|
+
|
123
|
+
account = Account.accept_invitation!(:invitation_token => account.invitation_token,
|
124
|
+
:password => 'testpass',
|
125
|
+
:password_confirmation => 'testpass',
|
126
|
+
:skip_email => true)
|
127
|
+
assert old_encrypted_password != account.encrypted_password
|
128
|
+
end
|
129
|
+
|
130
|
+
should 'clear invitation token and set invitation_accepted_at while accepting the password' do
|
131
|
+
account = Account.invite!(:email => "#{Faker::Internet.user_name}_#{rand(0...1000)}@example.org", :skip_email => true)
|
132
|
+
|
133
|
+
assert account.invitation_token.present?
|
134
|
+
assert account.invitation_accepted_at.nil?
|
135
|
+
|
136
|
+
account.accept_invitation!()
|
137
|
+
account.reload
|
138
|
+
|
139
|
+
assert account.invitation_token.nil?
|
140
|
+
assert account.invitation_accepted_at
|
141
|
+
end
|
142
|
+
|
143
|
+
should 'clear invitation token while resetting the password' do
|
144
|
+
account = Account.invite!(:email => "#{Faker::Internet.user_name}_#{rand(0...1000)}@example.org", :skip_email => true)
|
145
|
+
account.generate_reset_password_token!
|
146
|
+
|
147
|
+
assert account.reset_password_token
|
148
|
+
assert account.invitation_token
|
149
|
+
|
150
|
+
Account.reset_password_by_token(:reset_password_token => account.reset_password_token,
|
151
|
+
:password => '123456789',
|
152
|
+
:password_confirmation => '123456789',
|
153
|
+
:skip_email => true)
|
154
|
+
assert account.reload.invitation_token.nil?
|
155
|
+
end
|
156
|
+
|
157
|
+
should 'return a record with invitation token and no errors to send invitation by email' do
|
158
|
+
email = "#{Faker::Internet.user_name}_#{rand(0...1000)}@example.org"
|
159
|
+
invited_account = Account.invite!(:email => email, :skip_email => true)
|
160
|
+
|
161
|
+
assert invited_account.errors.blank?
|
162
|
+
assert invited_account.invitation_token
|
163
|
+
|
164
|
+
assert email == invited_account.email
|
165
|
+
assert invited_account.persisted?
|
166
|
+
end
|
167
|
+
|
168
|
+
should 'set all attributes with no errors' do
|
169
|
+
Account.stubs(:invite_key).returns(:email => Revise.email_regexp, :username => /\A.+\z/)
|
170
|
+
username = "#{Faker::Internet.user_name}_#{rand(0...1000)}"
|
171
|
+
invited_account = Account.invite!(:email => "#{Faker::Internet.user_name}_#{rand(0...1000)}@example.org",
|
172
|
+
:username => username)
|
173
|
+
|
174
|
+
assert invited_account.errors.blank?
|
175
|
+
assert username == invited_account.username
|
176
|
+
assert invited_account.persisted?
|
177
|
+
end
|
178
|
+
|
179
|
+
should 'not validate other attributes when validate_on_invite is disabled' do
|
180
|
+
validate_on_invite = Account.validate_on_invite
|
181
|
+
Account.validate_on_invite = false
|
182
|
+
invited_account = Account.invite!(:email => "#{Faker::Internet.user_name}_#{rand(0...1000)}@example.org", :username => "#{Faker::Internet.user_name}_#{rand(0...1000)}", :skip_email => true)
|
183
|
+
assert invited_account.errors.empty?
|
184
|
+
Account.validate_on_invite = validate_on_invite
|
185
|
+
end
|
186
|
+
|
187
|
+
should 'validate other attributes when validate_on_invite is enabled' do
|
188
|
+
Account.stubs(:invite_key).returns(:email => Revise.email_regexp, :username => /\A.+\z/)
|
189
|
+
validate_on_invite = Account.validate_on_invite
|
190
|
+
Account.validate_on_invite = true
|
191
|
+
invited_account = Account.invite!(:email => "#{Faker::Internet.user_name}_#{rand(0...1000)}@example.org", :username => 'invalid_username', :skip_email => true)
|
192
|
+
assert invited_account.errors[:username].present?
|
193
|
+
Account.validate_on_invite = validate_on_invite
|
194
|
+
end
|
195
|
+
|
196
|
+
should 'not validate password when validate_on_invite is enabled' do
|
197
|
+
validate_on_invite = Account.validate_on_invite
|
198
|
+
Account.validate_on_invite = true
|
199
|
+
invited_account = Account.invite!(:email => "#{Faker::Internet.user_name}_#{rand(0...1000)}@example.org", :username => "#{Faker::Internet.user_name}_#{rand(0...1000)}")
|
200
|
+
|
201
|
+
assert invited_account.errors.empty?
|
202
|
+
assert invited_account.errors[:password].empty?
|
203
|
+
Account.validate_on_invite = validate_on_invite
|
204
|
+
end
|
205
|
+
|
206
|
+
should 'validate other attributes when validate_on_invite is enabled and email is not present' do
|
207
|
+
Account.stubs(:invite_key).returns(:email => Revise.email_regexp, :username => /\A.+\z/)
|
208
|
+
validate_on_invite = Account.validate_on_invite
|
209
|
+
Account.validate_on_invite = true
|
210
|
+
invited_account = Account.invite!(:email => 'invalid_email', :username => 'invalid_username', :skip_email => true)
|
211
|
+
|
212
|
+
assert invited_account.errors[:email].present?
|
213
|
+
assert invited_account.errors[:username].present?
|
214
|
+
Account.validate_on_invite = validate_on_invite
|
215
|
+
end
|
216
|
+
|
217
|
+
should 'return a record with errors if account was found by e-mail' do
|
218
|
+
email = "#{Faker::Internet.user_name}_#{rand(0...1000)}@example.org"
|
219
|
+
existing_account = FactoryGirl.create(:account, :email => email)
|
220
|
+
account = Account.invite!(:email => email, :skip_email => true)
|
221
|
+
assert account.email == existing_account.email
|
222
|
+
assert account.errors[:email].present?
|
223
|
+
end
|
224
|
+
|
225
|
+
should 'return a record with errors if account with pending invitation was found by e-mail' do
|
226
|
+
email = "#{Faker::Internet.user_name}_#{rand(0...1000)}@example.org"
|
227
|
+
existing_account = Account.invite!(:email => email, :validate => false)
|
228
|
+
account = Account.invite!(:email => email, :validate => false)
|
229
|
+
|
230
|
+
assert account.email == existing_account.email
|
231
|
+
assert [] == account.errors[:email]
|
232
|
+
|
233
|
+
resend_invitation = Account.resend_invitation
|
234
|
+
|
235
|
+
begin
|
236
|
+
Account.resend_invitation = false
|
237
|
+
|
238
|
+
account = Account.invite!(:email => email, :skip_email => true)
|
239
|
+
assert account.email == existing_account.email
|
240
|
+
assert account.errors[:email].present?
|
241
|
+
ensure
|
242
|
+
Account.resend_invitation = resend_invitation
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
should 'return a record with errors if account was found by e-mail with validate_on_invite' do
|
247
|
+
Account.stubs(:invite_key).returns(:email => Revise.email_regexp, :username => /\A.+\z/)
|
248
|
+
begin
|
249
|
+
validate_on_invite = Account.validate_on_invite
|
250
|
+
Account.validate_on_invite = true
|
251
|
+
|
252
|
+
email = "#{Faker::Internet.user_name}_#{rand(0...1000)}@example.org"
|
253
|
+
existing_account = FactoryGirl.create(:account, :email => email)
|
254
|
+
account = Account.invite!(:email => email, :username => 'invalid_username', :skip_email => true)
|
255
|
+
|
256
|
+
assert account.email == existing_account.email
|
257
|
+
assert account.errors[:email].present?
|
258
|
+
assert account.errors[:username].present?
|
259
|
+
ensure
|
260
|
+
Account.validate_on_invite = validate_on_invite
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
should 'return a new record with errors if e-mail is blank' do
|
265
|
+
invited_account = Account.invite!(:email => '', :skip_email => true)
|
266
|
+
assert invited_account.new_record?
|
267
|
+
assert ["can't be blank"] == invited_account.errors[:email]
|
268
|
+
end
|
269
|
+
|
270
|
+
should 'return a new record with errors if e-mail is invalid' do
|
271
|
+
invited_account = Account.invite!(:email => 'invalid_email')
|
272
|
+
assert invited_account.new_record?
|
273
|
+
assert invited_account.errors[:email].present?
|
274
|
+
end
|
275
|
+
|
276
|
+
should 'set all attributes with errors if e-mail is invalid' do
|
277
|
+
Account.stubs(:invite_key).returns(:email => Revise.email_regexp, :username => /\A.+\z/)
|
278
|
+
username = "#{Faker::Internet.user_name}_#{rand(0...1000)}"
|
279
|
+
invited_account = Account.invite!(:email => 'invalid_email', :username => username, :skip_email => true)
|
280
|
+
assert invited_account.new_record?
|
281
|
+
assert username == invited_account.username
|
282
|
+
assert invited_account.errors.present?
|
283
|
+
end
|
284
|
+
|
285
|
+
should 'find a account to set his password based on invitation_token' do
|
286
|
+
account = FactoryGirl.create(:account)
|
287
|
+
account.invite!
|
288
|
+
invited_account = Account.accept_invitation!(:invitation_token => account.invitation_token, :skip_email => true)
|
289
|
+
assert invited_account.email == account.email
|
290
|
+
end
|
291
|
+
|
292
|
+
should 'return a new record with errors if no invitation_token is found' do
|
293
|
+
invited_account = Account.accept_invitation!(:invitation_token => 'invalid_token', :skip_email => true)
|
294
|
+
assert invited_account.new_record?
|
295
|
+
assert ['is invalid'] == invited_account.errors[:invitation_token]
|
296
|
+
end
|
297
|
+
|
298
|
+
should 'return a new record with errors if invitation_token is blank' do
|
299
|
+
invited_account = Account.accept_invitation!(:invitation_token => '', :skip_email => true)
|
300
|
+
assert invited_account.new_record?
|
301
|
+
assert ["can't be blank"] == invited_account.errors[:invitation_token]
|
302
|
+
end
|
303
|
+
|
304
|
+
should 'return record with errors if invitation_token has expired' do
|
305
|
+
Account.stubs(:invite_for).returns(10.hours)
|
306
|
+
|
307
|
+
invited_account = Account.invite!(:email => "#{Faker::Internet.user_name}_#{rand(0...1000)}@example.org", :skip_email => true)
|
308
|
+
invited_account.invitation_sent_at = 2.days.ago
|
309
|
+
invited_account.save(:validate => false)
|
310
|
+
|
311
|
+
account = Account.accept_invitation!(:invitation_token => invited_account.invitation_token)
|
312
|
+
|
313
|
+
assert account == invited_account
|
314
|
+
assert ["is invalid"] == account.errors[:invitation_token]
|
315
|
+
end
|
316
|
+
|
317
|
+
should 'set successfully account password given the new password and confirmation' do
|
318
|
+
account = FactoryGirl.create(:account)
|
319
|
+
account.invite!
|
320
|
+
|
321
|
+
invited_account = Account.accept_invitation!(
|
322
|
+
:invitation_token => account.invitation_token,
|
323
|
+
:password => 'new_password',
|
324
|
+
:password_confirmation => 'new_password',
|
325
|
+
:skip_email => true
|
326
|
+
)
|
327
|
+
account.reload
|
328
|
+
|
329
|
+
assert account.valid_password?('new_password')
|
330
|
+
end
|
331
|
+
|
332
|
+
should 'return errors on other attributes even when password is valid' do
|
333
|
+
account = FactoryGirl.create(:account)
|
334
|
+
account.invite!
|
335
|
+
|
336
|
+
invited_account = Account.accept_invitation!(
|
337
|
+
:invitation_token => account.invitation_token,
|
338
|
+
:password => 'new_password',
|
339
|
+
:password_confirmation => 'new_password',
|
340
|
+
:username => 'invalid_username',
|
341
|
+
:skip_email => true
|
342
|
+
)
|
343
|
+
assert invited_account.errors[:username].present?
|
344
|
+
|
345
|
+
assert !account.valid_password?('new_password')
|
346
|
+
end
|
347
|
+
|
348
|
+
should 'not confirm account on invite' do
|
349
|
+
account = FactoryGirl.create(:account)
|
350
|
+
account.invite!
|
351
|
+
|
352
|
+
assert !account.confirmed?
|
353
|
+
end
|
354
|
+
|
355
|
+
should 'account.has_invitations_left? test' do
|
356
|
+
# By default with invitation_limit nil, users can send unlimited invitations
|
357
|
+
account = FactoryGirl.create(:account)
|
358
|
+
assert account.invitation_limit == 5
|
359
|
+
assert account.has_invitations_left?
|
360
|
+
|
361
|
+
# With invitation_limit set to a value, all users can send that many invitations
|
362
|
+
Account.stubs(:invitation_limit).returns(2)
|
363
|
+
assert account.has_invitations_left?
|
364
|
+
|
365
|
+
# With an individual invitation_limit of 0, a account shouldn't be able to send an invitation
|
366
|
+
account.invitation_limit = 0
|
367
|
+
assert account.save
|
368
|
+
assert !account.has_invitations_left?
|
369
|
+
|
370
|
+
# With in invitation_limit of 2, a account should be able to send two invitations
|
371
|
+
account.invitation_limit = 2
|
372
|
+
assert account.save
|
373
|
+
assert account.has_invitations_left?
|
374
|
+
end
|
375
|
+
|
376
|
+
should 'not set the invited_by attribute if not passed' do
|
377
|
+
account = FactoryGirl.create(:account)
|
378
|
+
account.invite!
|
379
|
+
assert account.invited_by.nil?
|
380
|
+
end
|
381
|
+
|
382
|
+
should 'set the invited_by attribute if passed' do
|
383
|
+
account = FactoryGirl.create(:account)
|
384
|
+
inviting_account = FactoryGirl.create(:account)
|
385
|
+
account.invite!(inviting_account)
|
386
|
+
assert inviting_account.id == account.invited_by.id
|
387
|
+
assert inviting_account.class.to_s == account.invited_by_type
|
388
|
+
end
|
389
|
+
|
390
|
+
should 'confirm account if confirmable' do
|
391
|
+
account = Account.invite!(:email => "#{Faker::Internet.user_name}_#{rand(0...1000)}@example.org")
|
392
|
+
account.accept_invitation!
|
393
|
+
|
394
|
+
assert account.confirmed?
|
395
|
+
end
|
396
|
+
|
397
|
+
should 'not confirm account if validation fails' do
|
398
|
+
Account.stubs(:invite_key).returns(:email => Revise.email_regexp, :username => /\A.+\z/)
|
399
|
+
account = Account.invite!(:email => "#{Faker::Internet.user_name}_#{rand(0...1000)}@example.org", :username => 'invalid_username')
|
400
|
+
account.accept_invitation!
|
401
|
+
|
402
|
+
assert !account.confirmed?
|
403
|
+
end
|
404
|
+
|
405
|
+
should 'return instance with errors if invitation_token is nil' do
|
406
|
+
registered_account = Account.create(:email => "#{Faker::Internet.user_name}_#{rand(0...1000)}@example.org", :password => '123456', :password_confirmation => '123456')
|
407
|
+
account = Account.accept_invitation!
|
408
|
+
assert !account.errors.empty?
|
409
|
+
end
|
410
|
+
|
411
|
+
should 'count accepted and not accepted invitations' do
|
412
|
+
old_invitation_not_accepted_count = Account.invitation_not_accepted.count
|
413
|
+
old_invitation_accepted_count = Account.invitation_accepted.count
|
414
|
+
|
415
|
+
Account.invite!(:email => "#{Faker::Internet.user_name}_#{rand(0...1000)}@example.org")
|
416
|
+
account = Account.invite!(:email => "#{Faker::Internet.user_name}_#{rand(0...1000)}@example.org")
|
417
|
+
|
418
|
+
assert Account.invitation_not_accepted.count > old_invitation_not_accepted_count
|
419
|
+
|
420
|
+
account.accept_invitation!
|
421
|
+
assert Account.invitation_accepted.count > old_invitation_accepted_count
|
422
|
+
end
|
423
|
+
end
|