behaviour 0.0.1.pre.alpha
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.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +47 -0
- data/Rakefile +7 -0
- data/behaviour.gemspec +27 -0
- data/lib/behaviour.rb +4 -0
- data/lib/behaviour/version.rb +3 -0
- data/lib/generators/behaviour/authentication/USAGE +2 -0
- data/lib/generators/behaviour/authentication/authentication_generator.rb +37 -0
- data/lib/generators/behaviour/authentication/templates/.rspec +1 -0
- data/lib/generators/behaviour/authentication/templates/features/authentication/reset_password.feature +13 -0
- data/lib/generators/behaviour/authentication/templates/features/authentication/sign_in.feature +28 -0
- data/lib/generators/behaviour/authentication/templates/features/authentication/sign_out.feature +7 -0
- data/lib/generators/behaviour/authentication/templates/features/authentication/sign_up.feature +19 -0
- data/lib/generators/behaviour/authentication/templates/features/authentication/update_account.feature +19 -0
- data/lib/generators/behaviour/authentication/templates/features/step_definitions/authentication.rb +184 -0
- data/lib/generators/behaviour/authentication/templates/features/support/authentication.rb +18 -0
- data/lib/generators/behaviour/authentication/templates/features/support/i18n.rb +1 -0
- data/lib/generators/behaviour/authentication/templates/features/support/rack_session_access.rb +1 -0
- data/lib/generators/behaviour/authentication/templates/features/support/rspec_syntax.rb +2 -0
- data/lib/generators/behaviour/authentication/templates/spec/controllers/authentication/reset_passwords_controller_spec.rb +99 -0
- data/lib/generators/behaviour/authentication/templates/spec/controllers/authentication/sessions_controller_spec.rb +98 -0
- data/lib/generators/behaviour/authentication/templates/spec/controllers/authentication/users_controller_spec.rb +107 -0
- data/lib/generators/behaviour/authentication/templates/spec/support/i18n.rb +14 -0
- data/lib/generators/behaviour/authentication/templates/spec/support/syntax.rb +6 -0
- data/spec/dummy/Gemfile +0 -0
- data/spec/dummy/bin/rails +2 -0
- data/spec/generators/behaviour/authentication/authentication_generator_spec.rb +62 -0
- data/spec/spec_helper.rb +2 -0
- metadata +149 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: addcbefac6e9175f7296597777e567bdf6a7c3ed
|
4
|
+
data.tar.gz: a48782fb7567f2a57d295bb84dd17cf9c44c467f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 9a3533c28b5e5c62833da6ebcff092c413dc6cd5384c0bc2324c2ee115486b63677399de03de3aa42d998afba6bbb1c3c657acfd65d8e7acf5bfaa8ae9c7ecb3
|
7
|
+
data.tar.gz: 7be2b5cdef36f6f4d2d97f7103fcf72d79245b3c9fbdb2e18d70906999337fb01ade2ea235e6f7c456e3b6d088ba47144e9dfc4244329f44ed01d0ab58e4371b
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Décio Ferreira
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
# Behaviour (alpha version)
|
2
|
+
|
3
|
+
Behaviour generates the tests you need, to implement new features from scratch on your application.
|
4
|
+
|
5
|
+
Currently, there is only one feature available: user authentication.
|
6
|
+
|
7
|
+
## About
|
8
|
+
|
9
|
+
Behaviour is a first attempt to rething the way we develop gems.
|
10
|
+
|
11
|
+
Instead of extending your code with the implementation for a new feature, the behaviour gem gives you the tests needed to confidently develop the new functionality.
|
12
|
+
|
13
|
+
Some of the advantages of this approach are:
|
14
|
+
|
15
|
+
* Learn by example, great source of community written tests
|
16
|
+
* Flexibility, easily adapt the generated tests to match the functionality wanted
|
17
|
+
* Testing, helps you writing tests for your application
|
18
|
+
* Freedom, to discover new ways of implementing features, and to adapt it to your own style/project
|
19
|
+
* Adaptable/dynamic, be in control of what features to implement, and how to implement them
|
20
|
+
|
21
|
+
## Installation
|
22
|
+
|
23
|
+
Add this line to your application's Gemfile:
|
24
|
+
|
25
|
+
gem 'behaviour', :group => :development
|
26
|
+
|
27
|
+
And then execute:
|
28
|
+
|
29
|
+
$ bundle
|
30
|
+
|
31
|
+
Or install it yourself as:
|
32
|
+
|
33
|
+
$ gem install behaviour
|
34
|
+
|
35
|
+
## Usage
|
36
|
+
|
37
|
+
To generate the features and specs for the user authentication system run:
|
38
|
+
|
39
|
+
$ rails generate behaviour:authentication
|
40
|
+
|
41
|
+
## Contributing
|
42
|
+
|
43
|
+
1. Fork it ( http://github.com/decioferreira/behaviour/fork )
|
44
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
45
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
46
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
47
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/behaviour.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'behaviour/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "behaviour"
|
8
|
+
spec.version = Behaviour::VERSION
|
9
|
+
spec.authors = ["Décio Ferreira"]
|
10
|
+
spec.email = ["decio.ferreira@decioferreira.com"]
|
11
|
+
spec.summary = %q{Specify your application's behaviour.}
|
12
|
+
spec.description = %q{Add new features to your application by specifying behaviour.}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_runtime_dependency "rails"
|
22
|
+
|
23
|
+
spec.add_development_dependency "ammeter"
|
24
|
+
spec.add_development_dependency "bundler", "~> 1.5"
|
25
|
+
spec.add_development_dependency "rake"
|
26
|
+
spec.add_development_dependency "rspec"
|
27
|
+
end
|
data/lib/behaviour.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
module Behaviour
|
2
|
+
module Generators
|
3
|
+
class AuthenticationGenerator < ::Rails::Generators::Base
|
4
|
+
source_root File.expand_path('../templates', __FILE__)
|
5
|
+
|
6
|
+
def gem_dependencies
|
7
|
+
gem_group :development, :test do
|
8
|
+
gem "rspec-rails", version: "~> 3.0.0.beta"
|
9
|
+
gem "rack_session_access"
|
10
|
+
end
|
11
|
+
|
12
|
+
gem_group :test do
|
13
|
+
gem "cucumber-rails", require: false
|
14
|
+
gem "database_cleaner"
|
15
|
+
end
|
16
|
+
|
17
|
+
run "bundle install"
|
18
|
+
end
|
19
|
+
|
20
|
+
def cucumber_setup
|
21
|
+
generate "cucumber:install"
|
22
|
+
end
|
23
|
+
|
24
|
+
def rspec_setup
|
25
|
+
generate "rspec:install"
|
26
|
+
end
|
27
|
+
|
28
|
+
def copy_spec_files
|
29
|
+
directory "spec"
|
30
|
+
end
|
31
|
+
|
32
|
+
def copy_feature_files
|
33
|
+
directory "features"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
@@ -0,0 +1,13 @@
|
|
1
|
+
Feature: Reset password
|
2
|
+
Scenario: Receive reset password email
|
3
|
+
Given I am a registered user
|
4
|
+
When I ask for a password reset
|
5
|
+
Then I should receive a password reset email
|
6
|
+
And I should see a reset password email sent message
|
7
|
+
|
8
|
+
Scenario: Successful password reset
|
9
|
+
Given I received a password reset email
|
10
|
+
When I follow the reset password link
|
11
|
+
And I submit a valid new password
|
12
|
+
Then I should see a successful password reset message
|
13
|
+
And I should be signed in
|
data/lib/generators/behaviour/authentication/templates/features/authentication/sign_in.feature
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
Feature: Sign in
|
2
|
+
Scenario: Unauthenticated
|
3
|
+
When I access a page with restricted access
|
4
|
+
Then I should be redirected to the sign in page
|
5
|
+
And I should see an unauthenticated user message
|
6
|
+
|
7
|
+
Scenario: Successful sign in
|
8
|
+
Given I am a registered user
|
9
|
+
When I sign in with valid user data
|
10
|
+
Then I should see a successful sign in message
|
11
|
+
And I should be signed in
|
12
|
+
|
13
|
+
Scenario: Unregistered email
|
14
|
+
When I try to sign in with an unregistered email
|
15
|
+
Then I should see an invalid email message
|
16
|
+
And I should be signed out
|
17
|
+
|
18
|
+
Scenario: Wrong password
|
19
|
+
Given I am a registered user
|
20
|
+
When I try to sign in with a wrong password
|
21
|
+
Then I should see an invalid password message
|
22
|
+
And I should be signed out
|
23
|
+
|
24
|
+
Scenario: Already authenticated
|
25
|
+
Given I am signed in
|
26
|
+
When I access the sign in page
|
27
|
+
Then I should be redirected to the homepage
|
28
|
+
And I should see an already authenticated message
|
data/lib/generators/behaviour/authentication/templates/features/authentication/sign_up.feature
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Feature: Sign up
|
2
|
+
Scenario: Successful sign up
|
3
|
+
When I sign up with valid user data
|
4
|
+
Then I should be redirected to the homepage
|
5
|
+
And I should see a successful sign up message
|
6
|
+
And I should be signed in
|
7
|
+
|
8
|
+
Scenario: Already authenticated
|
9
|
+
Given I am signed in
|
10
|
+
When I access the sign up page
|
11
|
+
Then I should be redirected to the homepage
|
12
|
+
And I should see an already authenticated, sign out an try again message
|
13
|
+
|
14
|
+
Scenario: Already registered
|
15
|
+
Given I am a registered user
|
16
|
+
And I am signed out
|
17
|
+
When I sign up with valid user data
|
18
|
+
Then I should see an already registered message
|
19
|
+
And I should be signed out
|
@@ -0,0 +1,19 @@
|
|
1
|
+
Feature: Update Account
|
2
|
+
Scenario: Successful account update
|
3
|
+
Given I am signed in
|
4
|
+
When I update my password
|
5
|
+
Then I should see a successful account update message
|
6
|
+
And I should be signed in
|
7
|
+
|
8
|
+
Scenario: No current password
|
9
|
+
Given I am signed in
|
10
|
+
When I try to update my password without the current password
|
11
|
+
Then I should see a current password required message
|
12
|
+
|
13
|
+
Scenario: Sign in after account update
|
14
|
+
Given I am signed in
|
15
|
+
When I update my password
|
16
|
+
And I sign out
|
17
|
+
And I sign in with the new password
|
18
|
+
Then I should see a successful sign in message
|
19
|
+
And I should be signed in
|
data/lib/generators/behaviour/authentication/templates/features/step_definitions/authentication.rb
ADDED
@@ -0,0 +1,184 @@
|
|
1
|
+
Given(/^I am a registered user$/) do
|
2
|
+
steps %Q{
|
3
|
+
Given I sign up with valid user data
|
4
|
+
And I sign out
|
5
|
+
}
|
6
|
+
end
|
7
|
+
|
8
|
+
When(/^I ask for a password reset$/) do
|
9
|
+
visit "/reset_password"
|
10
|
+
fill_in "Email", with: user.email
|
11
|
+
click_button I18n.t("authentication.ask_reset_password_email.submit")
|
12
|
+
end
|
13
|
+
|
14
|
+
Then(/^I should receive a password reset email$/) do
|
15
|
+
expect(first_email.subject).to eq(I18n.t("authentication.email.reset_password.subject"))
|
16
|
+
end
|
17
|
+
|
18
|
+
Then(/^I should see a reset password email sent message$/) do
|
19
|
+
expect(page).to have_selector("#notice-message", text: I18n.t("authentication.notice.successfully_sent_reset_password_email"))
|
20
|
+
end
|
21
|
+
|
22
|
+
Given(/^I received a password reset email$/) do
|
23
|
+
steps %Q{
|
24
|
+
Given I am a registered user
|
25
|
+
And I ask for a password reset
|
26
|
+
Then I should receive a password reset email
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
When(/^I follow the reset password link$/) do
|
31
|
+
visit reset_password_path_from_email(first_email.body)
|
32
|
+
end
|
33
|
+
|
34
|
+
When(/^I submit a valid new password$/) do
|
35
|
+
fill_in "Password", with: user.new_password
|
36
|
+
fill_in "Confirm password", with: user.new_password
|
37
|
+
click_button I18n.t("authentication.reset_password.submit")
|
38
|
+
end
|
39
|
+
|
40
|
+
Then(/^I should see a successful password reset message$/) do
|
41
|
+
expect(page).to have_selector("#notice-message", text: I18n.t("authentication.notice.successfully_reset_password"))
|
42
|
+
end
|
43
|
+
|
44
|
+
Then(/^I should be signed in$/) do
|
45
|
+
expect { page.get_rack_session_key("user_id") }.not_to raise_error
|
46
|
+
end
|
47
|
+
|
48
|
+
When(/^I access a page with restricted access$/) do
|
49
|
+
visit "/restricted"
|
50
|
+
end
|
51
|
+
|
52
|
+
Then(/^I should be redirected to the sign in page$/) do
|
53
|
+
expect(current_path).to eq("/sign_in")
|
54
|
+
end
|
55
|
+
|
56
|
+
Then(/^I should see an unauthenticated user message$/) do
|
57
|
+
expect(page).to have_selector("#alert-message", text: I18n.t("authentication.alert.unauthenticated_user"))
|
58
|
+
end
|
59
|
+
|
60
|
+
When(/^I sign in with valid user data$/) do
|
61
|
+
visit "/sign_in"
|
62
|
+
fill_in "Email", with: user.email
|
63
|
+
fill_in "Password", with: user.password
|
64
|
+
click_button I18n.t("authentication.sign_in.submit")
|
65
|
+
end
|
66
|
+
|
67
|
+
Then(/^I should see a successful sign in message$/) do
|
68
|
+
expect(page).to have_selector("#notice-message", text: I18n.t("authentication.notice.successfully_signed_in"))
|
69
|
+
end
|
70
|
+
|
71
|
+
When(/^I try to sign in with an unregistered email$/) do
|
72
|
+
visit "/sign_in"
|
73
|
+
fill_in "Email", with: "unregistered@email.com"
|
74
|
+
fill_in "Password", with: user.password
|
75
|
+
click_button I18n.t("authentication.sign_in.submit")
|
76
|
+
end
|
77
|
+
|
78
|
+
Then(/^I should see an invalid email message$/) do
|
79
|
+
expect(page).to have_selector("#alert-message", text: I18n.t("authentication.alert.invalid_email"))
|
80
|
+
end
|
81
|
+
|
82
|
+
Then(/^I should be signed out$/) do
|
83
|
+
expect { page.get_rack_session_key("user_id") }.to raise_error(KeyError)
|
84
|
+
end
|
85
|
+
|
86
|
+
When(/^I try to sign in with a wrong password$/) do
|
87
|
+
visit "/sign_in"
|
88
|
+
fill_in "Email", with: user.email
|
89
|
+
fill_in "Password", with: "wrong_password"
|
90
|
+
click_button I18n.t("authentication.sign_in.submit")
|
91
|
+
end
|
92
|
+
|
93
|
+
Then(/^I should see an invalid password message$/) do
|
94
|
+
expect(page).to have_selector("#alert-message", text: I18n.t("authentication.alert.invalid_password"))
|
95
|
+
end
|
96
|
+
|
97
|
+
Given(/^I am signed in$/) do
|
98
|
+
steps %Q{
|
99
|
+
Given I sign up with valid user data
|
100
|
+
Then I should be signed in
|
101
|
+
}
|
102
|
+
end
|
103
|
+
|
104
|
+
When(/^I access the sign in page$/) do
|
105
|
+
visit "/sign_in"
|
106
|
+
end
|
107
|
+
|
108
|
+
Then(/^I should be redirected to the homepage$/) do
|
109
|
+
expect(current_path).to eq("/")
|
110
|
+
end
|
111
|
+
|
112
|
+
Then(/^I should see an already authenticated message$/) do
|
113
|
+
expect(page).to have_selector("#alert-message", text: I18n.t("authentication.alert.already_authenticated"))
|
114
|
+
end
|
115
|
+
|
116
|
+
When(/^I sign out$/) do
|
117
|
+
visit "/" unless page.has_button?("Sign out")
|
118
|
+
click_button I18n.t("authentication.sign_out.submit")
|
119
|
+
end
|
120
|
+
|
121
|
+
Then(/^I should see a successful sign out message$/) do
|
122
|
+
expect(page).to have_selector("#notice-message", text: I18n.t("authentication.notice.successfully_signed_out"))
|
123
|
+
end
|
124
|
+
|
125
|
+
When(/^I sign up with valid user data$/) do
|
126
|
+
visit "/sign_up"
|
127
|
+
fill_in "Email", with: user.email
|
128
|
+
fill_in "Password", with: user.password
|
129
|
+
fill_in "Confirm password", with: user.password
|
130
|
+
click_button I18n.t("authentication.sign_up.submit")
|
131
|
+
end
|
132
|
+
|
133
|
+
Then(/^I should see a successful sign up message$/) do
|
134
|
+
expect(page).to have_selector("#notice-message", text: I18n.t("authentication.notice.successfully_signed_up"))
|
135
|
+
end
|
136
|
+
|
137
|
+
When(/^I access the sign up page$/) do
|
138
|
+
visit "/sign_up"
|
139
|
+
end
|
140
|
+
|
141
|
+
Then(/^I should see an already authenticated, sign out an try again message$/) do
|
142
|
+
expect(page).to have_selector("#alert-message", text: I18n.t("authentication.alert.authenticated_sign_out_try_again"))
|
143
|
+
end
|
144
|
+
|
145
|
+
Given(/^I am signed out$/) do
|
146
|
+
visit "/" unless page.has_button?(I18n.t("authentication.action.sign_out"))
|
147
|
+
click_button I18n.t("authentication.action.sign_out")
|
148
|
+
end
|
149
|
+
|
150
|
+
Then(/^I should see an already registered message$/) do
|
151
|
+
expect(page).to have_selector("#alert-message", text: I18n.t("authentication.alert.already_registered"))
|
152
|
+
end
|
153
|
+
|
154
|
+
When(/^I update my password$/) do
|
155
|
+
visit "/account/edit"
|
156
|
+
fill_in "Password", with: user.new_password
|
157
|
+
fill_in "Confirm password", with: user.new_password
|
158
|
+
fill_in "Current password", with: user.password
|
159
|
+
click_button I18n.t("authentication.update_account.submit")
|
160
|
+
end
|
161
|
+
|
162
|
+
Then(/^I should see a successful account update message$/) do
|
163
|
+
expect(page).to have_selector("#notice-message", text: I18n.t("authentication.notice.successfully_updated_account"))
|
164
|
+
end
|
165
|
+
|
166
|
+
When(/^I try to update my password without the current password$/) do
|
167
|
+
visit "/account/edit"
|
168
|
+
fill_in "Password", with: user.new_password
|
169
|
+
fill_in "Confirm password", with: user.new_password
|
170
|
+
fill_in "Current password", with: ""
|
171
|
+
click_button I18n.t("authentication.update_account.submit")
|
172
|
+
end
|
173
|
+
|
174
|
+
Then(/^I should see a current password required message$/) do
|
175
|
+
expect(page).to have_selector("#alert-message", text: I18n.t("authentication.alert.current_password_required"))
|
176
|
+
end
|
177
|
+
|
178
|
+
When(/^I sign in with the new password$/) do
|
179
|
+
visit "/sign_in"
|
180
|
+
fill_in "Email", with: user.email
|
181
|
+
fill_in "Password", with: user.new_password
|
182
|
+
click_button I18n.t("authentication.sign_in.submit")
|
183
|
+
save_page
|
184
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Authentication
|
2
|
+
def user
|
3
|
+
OpenStruct.new(
|
4
|
+
email: "user@email.com",
|
5
|
+
password: "password"
|
6
|
+
)
|
7
|
+
end
|
8
|
+
|
9
|
+
def first_email
|
10
|
+
ActionMailer::Base.deliveries.first
|
11
|
+
end
|
12
|
+
|
13
|
+
def reset_password_path_from_email(body)
|
14
|
+
body.match(/https?:\/\/[^\/]+(\/reset\_password\/edit\?token=\h+)/)[1]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
World(Authentication)
|
@@ -0,0 +1 @@
|
|
1
|
+
require_relative "../../spec/support/i18n"
|
data/lib/generators/behaviour/authentication/templates/features/support/rack_session_access.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "rack_session_access/capybara"
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Authentication::ResetPasswordsController do
|
4
|
+
describe "GET new" do
|
5
|
+
context "when I am not logged in" do
|
6
|
+
before :each do
|
7
|
+
allow(controller).to receive(:signed_in?) { false }
|
8
|
+
get :new
|
9
|
+
end
|
10
|
+
|
11
|
+
it { expect(response).to render_template(:new) }
|
12
|
+
it { expect(response).to be_success }
|
13
|
+
end
|
14
|
+
|
15
|
+
context "when I am logged in" do
|
16
|
+
before :each do
|
17
|
+
allow(controller).to receive(:signed_in?) { true }
|
18
|
+
get :new
|
19
|
+
end
|
20
|
+
|
21
|
+
it { expect(response).to redirect_to root_path }
|
22
|
+
it { expect(flash[:alert]).to eq(I18n.t("authentication.alert.authenticated_sign_out_try_again")) }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "POST create" do
|
27
|
+
context "when I am not logged in" do
|
28
|
+
let(:mailer) { double(:mailer).as_null_object }
|
29
|
+
let!(:user) { User.create(email: "valid@email.com", password: "password") }
|
30
|
+
|
31
|
+
before :each do
|
32
|
+
allow(AuthenticationMailer).to receive(:reset_password).and_return(mailer)
|
33
|
+
post :create, email: "valid@email.com"
|
34
|
+
end
|
35
|
+
|
36
|
+
it { expect(AuthenticationMailer).to have_received(:reset_password).with(user) }
|
37
|
+
it { expect(mailer).to have_received(:deliver) }
|
38
|
+
it { expect(flash[:notice]).to eq(I18n.t("authentication.notice.successfully_sent_reset_password_email")) }
|
39
|
+
it { expect(response).to render_template(:new) }
|
40
|
+
it { expect(response).to be_success }
|
41
|
+
end
|
42
|
+
|
43
|
+
context "when I am logged in" do
|
44
|
+
before :each do
|
45
|
+
allow(controller).to receive(:signed_in?) { true }
|
46
|
+
post :create
|
47
|
+
end
|
48
|
+
|
49
|
+
it { expect(response).to redirect_to root_path }
|
50
|
+
it { expect(flash[:alert]).to eq(I18n.t("authentication.alert.authenticated_sign_out_try_again")) }
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "GET edit" do
|
55
|
+
context "when I am not logged in" do
|
56
|
+
before :each do
|
57
|
+
allow(controller).to receive(:signed_in?) { false }
|
58
|
+
get :edit
|
59
|
+
end
|
60
|
+
|
61
|
+
it { expect(response).to render_template(:edit) }
|
62
|
+
it { expect(response).to be_success }
|
63
|
+
end
|
64
|
+
|
65
|
+
context "when I am logged in" do
|
66
|
+
before :each do
|
67
|
+
allow(controller).to receive(:signed_in?) { true }
|
68
|
+
get :edit
|
69
|
+
end
|
70
|
+
|
71
|
+
it { expect(response).to redirect_to root_path }
|
72
|
+
it { expect(flash[:alert]).to eq(I18n.t("authentication.alert.authenticated_sign_out_try_again")) }
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
describe "PUT update" do
|
77
|
+
context "when I am not logged in" do
|
78
|
+
let!(:user) { User.create(email: "valid@email.com", password: "password") }
|
79
|
+
|
80
|
+
before :each do
|
81
|
+
put :update
|
82
|
+
end
|
83
|
+
|
84
|
+
it { expect(flash[:notice]).to eq(I18n.t("authentication.notice.successfully_reset_password")) }
|
85
|
+
it { expect(response).to render_template(:edit) }
|
86
|
+
it { expect(response).to be_success }
|
87
|
+
end
|
88
|
+
|
89
|
+
context "when I am logged in" do
|
90
|
+
before :each do
|
91
|
+
allow(controller).to receive(:signed_in?) { true }
|
92
|
+
put :update
|
93
|
+
end
|
94
|
+
|
95
|
+
it { expect(response).to redirect_to root_path }
|
96
|
+
it { expect(flash[:alert]).to eq(I18n.t("authentication.alert.authenticated_sign_out_try_again")) }
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Authentication::SessionsController do
|
4
|
+
describe "GET new" do
|
5
|
+
context "when I am not logged in" do
|
6
|
+
before :each do
|
7
|
+
allow(controller).to receive(:signed_in?) { false }
|
8
|
+
get :new
|
9
|
+
end
|
10
|
+
|
11
|
+
it { expect(response).to be_success }
|
12
|
+
end
|
13
|
+
|
14
|
+
context "when I am logged in" do
|
15
|
+
before :each do
|
16
|
+
allow(controller).to receive(:signed_in?) { true }
|
17
|
+
get :new
|
18
|
+
end
|
19
|
+
|
20
|
+
it { expect(response).to redirect_to root_path }
|
21
|
+
it { expect(flash[:alert]).to eq(I18n.t("authentication.alert.already_authenticated")) }
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "POST create" do
|
26
|
+
context "when I am not logged in" do
|
27
|
+
before :each do
|
28
|
+
allow(controller).to receive(:signed_in?) { false }
|
29
|
+
end
|
30
|
+
|
31
|
+
context "when I am successfully registered" do
|
32
|
+
let!(:user) { User.create(email: "valid@email.com", password: "validpassword") }
|
33
|
+
|
34
|
+
context "when I sign in with a valid email" do
|
35
|
+
before :each do
|
36
|
+
post :create, email: "valid@email.com", password: "validpassword"
|
37
|
+
end
|
38
|
+
|
39
|
+
it { expect(response).to redirect_to root_path }
|
40
|
+
it { expect(flash[:notice]).to eq(I18n.t("authentication.notice.successfully_signed_in")) }
|
41
|
+
it { expect(session[:user_id]).to eq(user.id) }
|
42
|
+
end
|
43
|
+
|
44
|
+
context "when I sign in with an invalid email" do
|
45
|
+
before :each do
|
46
|
+
post :create, email: "invalid@email.com", password: "password"
|
47
|
+
end
|
48
|
+
|
49
|
+
it { expect(response).to be_success }
|
50
|
+
it { expect(flash[:alert]).to eq(I18n.t("authentication.alert.invalid_email")) }
|
51
|
+
end
|
52
|
+
|
53
|
+
context "when I sign in with an invalid password" do
|
54
|
+
before :each do
|
55
|
+
post :create, email: "valid@email.com", password: "invalid"
|
56
|
+
end
|
57
|
+
|
58
|
+
it { expect(response).to be_success }
|
59
|
+
it { expect(flash[:alert]).to eq(I18n.t("authentication.alert.invalid_password")) }
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
context "when I am logged in" do
|
65
|
+
before :each do
|
66
|
+
allow(controller).to receive(:signed_in?) { true }
|
67
|
+
post :create
|
68
|
+
end
|
69
|
+
|
70
|
+
it { expect(response).to redirect_to root_path }
|
71
|
+
it { expect(flash[:alert]).to eq(I18n.t("authentication.alert.already_authenticated")) }
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe "DELETE destroy" do
|
76
|
+
context "when I am not logged in" do
|
77
|
+
before :each do
|
78
|
+
delete :destroy
|
79
|
+
end
|
80
|
+
|
81
|
+
it { expect(response).to redirect_to root_path }
|
82
|
+
it { expect(flash[:notice]).to eq(I18n.t("authentication.notice.successfully_signed_out")) }
|
83
|
+
end
|
84
|
+
|
85
|
+
context "when I am logged in" do
|
86
|
+
let!(:user) { User.create(email: "valid@email.com", password: "validpassword") }
|
87
|
+
|
88
|
+
before :each do
|
89
|
+
session[:user_id] = user.id
|
90
|
+
delete :destroy
|
91
|
+
end
|
92
|
+
|
93
|
+
it { expect(response).to redirect_to root_path }
|
94
|
+
it { expect(flash[:notice]).to eq(I18n.t("authentication.notice.successfully_signed_out")) }
|
95
|
+
it { expect(session[:user_id]).to be_nil }
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Authentication::UsersController do
|
4
|
+
describe "GET new" do
|
5
|
+
context "when I am not logged in" do
|
6
|
+
before :each do
|
7
|
+
allow(controller).to receive(:signed_in?) { false }
|
8
|
+
get :new
|
9
|
+
end
|
10
|
+
|
11
|
+
it { expect(response).to be_success }
|
12
|
+
end
|
13
|
+
|
14
|
+
context "when I am logged in" do
|
15
|
+
before :each do
|
16
|
+
allow(controller).to receive(:signed_in?) { true }
|
17
|
+
get :new
|
18
|
+
end
|
19
|
+
|
20
|
+
it { expect(response).to redirect_to root_path }
|
21
|
+
it { expect(flash[:alert]).to eq(I18n.t("authentication.alert.authenticated_sign_out_try_again")) }
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "POST create" do
|
26
|
+
context "when I am not logged in" do
|
27
|
+
before :each do
|
28
|
+
allow(controller).to receive(:signed_in?) { false }
|
29
|
+
end
|
30
|
+
|
31
|
+
context "when I submit valid data" do
|
32
|
+
before :each do
|
33
|
+
allow(controller).to receive(:signed_in?) { false }
|
34
|
+
post :create, email: "valid@email.com", password: "password"
|
35
|
+
end
|
36
|
+
|
37
|
+
it { expect(response).to redirect_to root_path }
|
38
|
+
it { expect(flash[:notice]).to eq(I18n.t("authentication.notice.successfully_signed_up")) }
|
39
|
+
|
40
|
+
it "logs me in" do
|
41
|
+
expect(User.count).to eq(1)
|
42
|
+
expect(session[:user_id]).to eq(User.first.id)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context "when I am logged in" do
|
48
|
+
before :each do
|
49
|
+
allow(controller).to receive(:signed_in?) { true }
|
50
|
+
post :create
|
51
|
+
end
|
52
|
+
|
53
|
+
it { expect(response).to redirect_to root_path }
|
54
|
+
it { expect(flash[:alert]).to eq(I18n.t("authentication.alert.authenticated_sign_out_try_again")) }
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe "GET edit" do
|
59
|
+
context "when I am not logged in" do
|
60
|
+
before :each do
|
61
|
+
allow(controller).to receive(:signed_in?) { false }
|
62
|
+
get :edit
|
63
|
+
end
|
64
|
+
|
65
|
+
it { expect(response).to redirect_to root_path }
|
66
|
+
it { expect(flash[:alert]).to eq(I18n.t("authentication.alert.unauthenticated_user")) }
|
67
|
+
end
|
68
|
+
|
69
|
+
context "when I am logged in" do
|
70
|
+
before :each do
|
71
|
+
allow(controller).to receive(:signed_in?) { true }
|
72
|
+
get :edit
|
73
|
+
end
|
74
|
+
|
75
|
+
it { expect(response).to be_success }
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe "PUT update" do
|
80
|
+
context "when I am not logged in" do
|
81
|
+
before :each do
|
82
|
+
allow(controller).to receive(:signed_in?) { false }
|
83
|
+
put :update
|
84
|
+
end
|
85
|
+
|
86
|
+
it { expect(response).to redirect_to root_path }
|
87
|
+
it { expect(flash[:alert]).to eq(I18n.t("authentication.alert.unauthenticated_user")) }
|
88
|
+
end
|
89
|
+
|
90
|
+
context "when I am logged in" do
|
91
|
+
let(:user) { User.create(email: "valid@email.com", password: "password") }
|
92
|
+
|
93
|
+
before :each do
|
94
|
+
session[:user_id] = user.id
|
95
|
+
end
|
96
|
+
|
97
|
+
context "when I submit valid data" do
|
98
|
+
before :each do
|
99
|
+
put :update, password: "new_password", current_password: "password"
|
100
|
+
end
|
101
|
+
|
102
|
+
it { expect(response).to be_success }
|
103
|
+
it { expect(flash[:notice]).to eq(I18n.t("authentication.notice.successfully_updated_account")) }
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# Source: http://guides.rubyonrails.org/i18n.html#using-different-exception-handlers
|
2
|
+
module I18n
|
3
|
+
class JustRaiseExceptionHandler < ExceptionHandler
|
4
|
+
def call(exception, locale, key, options)
|
5
|
+
if exception.is_a?(MissingTranslation)
|
6
|
+
raise exception.to_exception
|
7
|
+
else
|
8
|
+
super
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
I18n.exception_handler = I18n::JustRaiseExceptionHandler.new
|
data/spec/dummy/Gemfile
ADDED
File without changes
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "generators/behaviour/authentication/authentication_generator"
|
3
|
+
|
4
|
+
describe Behaviour::Generators::AuthenticationGenerator do
|
5
|
+
# Tell the generator where to put its output (what it thinks of as Rails.root)
|
6
|
+
destination File.expand_path("../../../../../tmp", __FILE__)
|
7
|
+
|
8
|
+
before do
|
9
|
+
prepare_destination
|
10
|
+
FileUtils.cp_r "spec/dummy/.", destination_root
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "no arguments" do
|
14
|
+
before { run_generator }
|
15
|
+
|
16
|
+
describe "Gemfile" do
|
17
|
+
subject { file("Gemfile") }
|
18
|
+
|
19
|
+
it {
|
20
|
+
expect(subject).to contain <<-GROUP
|
21
|
+
group :development, :test do
|
22
|
+
gem "rspec-rails", "~> 3.0.0.beta"
|
23
|
+
gem "rack_session_access"
|
24
|
+
end
|
25
|
+
GROUP
|
26
|
+
}
|
27
|
+
|
28
|
+
it {
|
29
|
+
expect(subject).to contain <<-GROUP
|
30
|
+
group :test do
|
31
|
+
gem "cucumber-rails", require: false
|
32
|
+
gem "database_cleaner"
|
33
|
+
end
|
34
|
+
GROUP
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "features" do
|
39
|
+
it { expect(file("features/authentication/reset_password.feature")).to exist }
|
40
|
+
it { expect(file("features/authentication/sign_in.feature")).to exist }
|
41
|
+
it { expect(file("features/authentication/sign_out.feature")).to exist }
|
42
|
+
it { expect(file("features/authentication/sign_up.feature")).to exist }
|
43
|
+
it { expect(file("features/authentication/update_account.feature")).to exist }
|
44
|
+
|
45
|
+
it { expect(file("features/step_definitions/authentication.rb")).to exist }
|
46
|
+
|
47
|
+
it { expect(file("features/support/authentication.rb")).to exist }
|
48
|
+
it { expect(file("features/support/i18n.rb")).to exist }
|
49
|
+
it { expect(file("features/support/rack_session_access.rb")).to exist }
|
50
|
+
it { expect(file("features/support/rspec_syntax.rb")).to exist }
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "specs" do
|
54
|
+
it { expect(file("spec/controllers/authentication/reset_passwords_controller_spec.rb")).to exist }
|
55
|
+
it { expect(file("spec/controllers/authentication/sessions_controller_spec.rb")).to exist }
|
56
|
+
it { expect(file("spec/controllers/authentication/users_controller_spec.rb")).to exist }
|
57
|
+
|
58
|
+
it { expect(file("spec/support/i18n.rb")).to exist }
|
59
|
+
it { expect(file("spec/support/syntax.rb")).to exist }
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,149 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: behaviour
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1.pre.alpha
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Décio Ferreira
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-02-09 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: ammeter
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.5'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.5'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
description: Add new features to your application by specifying behaviour.
|
84
|
+
email:
|
85
|
+
- decio.ferreira@decioferreira.com
|
86
|
+
executables: []
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files: []
|
89
|
+
files:
|
90
|
+
- ".gitignore"
|
91
|
+
- ".rspec"
|
92
|
+
- Gemfile
|
93
|
+
- LICENSE.txt
|
94
|
+
- README.md
|
95
|
+
- Rakefile
|
96
|
+
- behaviour.gemspec
|
97
|
+
- lib/behaviour.rb
|
98
|
+
- lib/behaviour/version.rb
|
99
|
+
- lib/generators/behaviour/authentication/USAGE
|
100
|
+
- lib/generators/behaviour/authentication/authentication_generator.rb
|
101
|
+
- lib/generators/behaviour/authentication/templates/.rspec
|
102
|
+
- lib/generators/behaviour/authentication/templates/features/authentication/reset_password.feature
|
103
|
+
- lib/generators/behaviour/authentication/templates/features/authentication/sign_in.feature
|
104
|
+
- lib/generators/behaviour/authentication/templates/features/authentication/sign_out.feature
|
105
|
+
- lib/generators/behaviour/authentication/templates/features/authentication/sign_up.feature
|
106
|
+
- lib/generators/behaviour/authentication/templates/features/authentication/update_account.feature
|
107
|
+
- lib/generators/behaviour/authentication/templates/features/step_definitions/authentication.rb
|
108
|
+
- lib/generators/behaviour/authentication/templates/features/support/authentication.rb
|
109
|
+
- lib/generators/behaviour/authentication/templates/features/support/i18n.rb
|
110
|
+
- lib/generators/behaviour/authentication/templates/features/support/rack_session_access.rb
|
111
|
+
- lib/generators/behaviour/authentication/templates/features/support/rspec_syntax.rb
|
112
|
+
- lib/generators/behaviour/authentication/templates/spec/controllers/authentication/reset_passwords_controller_spec.rb
|
113
|
+
- lib/generators/behaviour/authentication/templates/spec/controllers/authentication/sessions_controller_spec.rb
|
114
|
+
- lib/generators/behaviour/authentication/templates/spec/controllers/authentication/users_controller_spec.rb
|
115
|
+
- lib/generators/behaviour/authentication/templates/spec/support/i18n.rb
|
116
|
+
- lib/generators/behaviour/authentication/templates/spec/support/syntax.rb
|
117
|
+
- spec/dummy/Gemfile
|
118
|
+
- spec/dummy/bin/rails
|
119
|
+
- spec/generators/behaviour/authentication/authentication_generator_spec.rb
|
120
|
+
- spec/spec_helper.rb
|
121
|
+
homepage: ''
|
122
|
+
licenses:
|
123
|
+
- MIT
|
124
|
+
metadata: {}
|
125
|
+
post_install_message:
|
126
|
+
rdoc_options: []
|
127
|
+
require_paths:
|
128
|
+
- lib
|
129
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
130
|
+
requirements:
|
131
|
+
- - ">="
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '0'
|
134
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: 1.3.1
|
139
|
+
requirements: []
|
140
|
+
rubyforge_project:
|
141
|
+
rubygems_version: 2.2.0.rc.1
|
142
|
+
signing_key:
|
143
|
+
specification_version: 4
|
144
|
+
summary: Specify your application's behaviour.
|
145
|
+
test_files:
|
146
|
+
- spec/dummy/Gemfile
|
147
|
+
- spec/dummy/bin/rails
|
148
|
+
- spec/generators/behaviour/authentication/authentication_generator_spec.rb
|
149
|
+
- spec/spec_helper.rb
|