saucy 0.15.2 → 0.16.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/CHANGELOG.md +3 -7
- data/Gemfile +1 -10
- data/Gemfile.lock +42 -3
- data/README.md +5 -0
- data/Rakefile +12 -3
- data/app/controllers/accounts_controller.rb +2 -1
- data/app/mailers/billing_mailer.rb +8 -0
- data/app/models/canceled_account.rb +12 -7
- data/app/views/accounts/_projects.html.erb +1 -1
- data/app/views/billing_mailer/cancelation_notification.text.erb +3 -0
- data/app/views/invitation_mailer/invitation.text.erb +1 -1
- data/app/views/invitations/show.html.erb +1 -1
- data/app/views/memberships/edit.html.erb +2 -2
- data/app/views/memberships/index.html.erb +1 -1
- data/app/views/projects/_form.html.erb +5 -5
- data/app/views/projects/edit.html.erb +2 -2
- data/app/views/projects/index.html.erb +3 -3
- data/app/views/projects/new.html.erb +1 -1
- data/app/views/shared/_project_dropdown.html.erb +3 -3
- data/config/routes.rb +2 -6
- data/cucumber.yml +1 -0
- data/{lib/generators/saucy/features/templates/features → features/engine}/admin_reporting.feature +0 -0
- data/{lib/generators/saucy/features/templates/features → features/engine}/edit_profile.feature +0 -0
- data/{lib/generators/saucy/features/templates/features → features/engine}/edit_project_permissions.feature +0 -0
- data/{lib/generators/saucy/features/templates/features → features/engine}/edit_user_permissions.feature +0 -0
- data/{lib/generators/saucy/features/templates/features → features/engine}/manage_account.feature +0 -0
- data/{lib/generators/saucy/features/templates/features → features/engine}/manage_billing.feature +1 -1
- data/{lib/generators/saucy/features/templates/features → features/engine}/manage_plan.feature +0 -0
- data/{lib/generators/saucy/features/templates/features → features/engine}/manage_projects.feature +0 -0
- data/{lib/generators/saucy/features/templates/features → features/engine}/manage_users.feature +0 -0
- data/{lib/generators/saucy/features/templates/features → features/engine}/new_account.feature +0 -0
- data/{lib/generators/saucy/features/templates/features → features/engine}/project_dropdown.feature +0 -0
- data/{lib/generators/saucy/features/templates/features → features/engine}/sign_up.feature +0 -0
- data/{lib/generators/saucy/features/templates/features → features/engine}/sign_up_coupon.feature +0 -0
- data/{lib/generators/saucy/features/templates/features → features/engine}/sign_up_paid.feature +0 -0
- data/{lib/generators/saucy/features/templates/features → features/engine}/trial_plans.feature +0 -0
- data/features/integration/run_features.feature +46 -0
- data/features/step_definitions/clearance_steps.rb +123 -0
- data/{lib/generators/saucy/features/templates/step_definitions → features/step_definitions/engine}/account_steps.rb +0 -0
- data/features/step_definitions/engine/braintree_steps.rb +24 -0
- data/{lib/generators/saucy/features/templates/step_definitions → features/step_definitions/engine}/country_steps.rb +0 -0
- data/{lib/generators/saucy/features/templates/step_definitions → features/step_definitions/engine}/cron_steps.rb +3 -5
- data/{lib/generators/saucy/features/templates/step_definitions → features/step_definitions/engine}/email_steps.rb +0 -0
- data/{lib/generators/saucy/features/templates/step_definitions → features/step_definitions/engine}/factory_girl_steps.rb +0 -0
- data/{lib/generators/saucy/features/templates/step_definitions → features/step_definitions/engine}/html_steps.rb +0 -0
- data/{lib/generators/saucy/features/templates/step_definitions → features/step_definitions/engine}/plan_steps.rb +0 -0
- data/{lib/generators/saucy/features/templates/step_definitions → features/step_definitions/engine}/project_steps.rb +0 -0
- data/{lib/generators/saucy/features/templates/step_definitions → features/step_definitions/engine}/session_steps.rb +0 -0
- data/{lib/generators/saucy/features/templates/step_definitions → features/step_definitions/engine}/user_steps.rb +0 -0
- data/features/step_definitions/rails_steps.rb +26 -8
- data/features/step_definitions/saucy_steps.rb +5 -0
- data/features/step_definitions/web_steps.rb +253 -0
- data/features/support/engine/braintree.rb +5 -0
- data/features/support/env.rb +18 -0
- data/features/support/factory_girl.rb +2 -0
- data/features/support/paths.rb +68 -0
- data/features/support/rails.rb +4 -0
- data/features/support/selectors.rb +11 -0
- data/lib/generators/saucy/features/features_generator.rb +7 -3
- data/lib/saucy/account.rb +55 -57
- data/lib/saucy/account_authorization.rb +39 -42
- data/lib/saucy/plan.rb +14 -16
- data/lib/saucy/project.rb +42 -44
- data/lib/saucy/projects_controller.rb +53 -55
- data/lib/saucy/subscription.rb +189 -191
- data/lib/saucy/user.rb +5 -7
- data/lib/saucy/version.rb +1 -1
- data/saucy.gemspec +21 -5
- data/spec/controllers/accounts_controller_spec.rb +2 -1
- data/spec/controllers/projects_controller_spec.rb +1 -1
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/assets/javascripts/application.js +9 -0
- data/spec/dummy/app/assets/stylesheets/application.css +7 -0
- data/spec/dummy/app/controllers/application_controller.rb +5 -0
- data/spec/dummy/app/controllers/homes_controller.rb +2 -0
- data/spec/dummy/app/controllers/projects_controller.rb +3 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/mailers/.gitkeep +0 -0
- data/spec/dummy/app/models/.gitkeep +0 -0
- data/spec/dummy/app/models/account.rb +3 -0
- data/spec/dummy/app/models/plan.rb +3 -0
- data/spec/dummy/app/models/project.rb +3 -0
- data/spec/dummy/app/models/user.rb +4 -0
- data/spec/dummy/app/views/homes/show.html.erb +1 -0
- data/spec/dummy/app/views/layouts/application.html.erb +24 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +48 -0
- data/spec/dummy/config/boot.rb +10 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +30 -0
- data/spec/dummy/config/environments/production.rb +60 -0
- data/spec/dummy/config/environments/test.rb +42 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/clearance.rb +3 -0
- data/spec/dummy/config/initializers/inflections.rb +10 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +7 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +5 -0
- data/spec/dummy/config/routes.rb +59 -0
- data/spec/dummy/db/migrate/20120201000751_create_diesel_clearance_users.rb +19 -0
- data/spec/dummy/db/migrate/20120201001546_create_saucy_tables.rb +122 -0
- data/spec/dummy/db/migrate/20120201001548_create_canceled_accounts.rb +14 -0
- data/spec/dummy/lib/assets/.gitkeep +0 -0
- data/spec/dummy/log/.gitkeep +0 -0
- data/spec/dummy/public/404.html +26 -0
- data/spec/dummy/public/422.html +26 -0
- data/spec/dummy/public/500.html +26 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/mailers/billing_mailer_spec.rb +12 -2
- data/spec/models/canceled_account_spec.rb +8 -6
- data/spec/models/subscription_spec.rb +47 -53
- data/spec/spec_helper.rb +8 -11
- data/spec/support/braintree.rb +2 -4
- data/spec/support/factories.rb +1 -0
- metadata +447 -125
- data/db/migrate/20120206155222_add_subscription_token_to_canceled_accounts.rb +0 -5
- data/features/run_features.feature +0 -84
- data/lib/generators/saucy/features/templates/step_definitions/braintree_steps.rb +0 -25
- data/lib/generators/saucy/features/templates/support/braintree.rb +0 -5
- data/lib/generators/saucy/specs/specs_generator.rb +0 -20
- data/lib/generators/saucy/specs/templates/support/braintree.rb +0 -5
- data/lib/saucy/fake_braintree.rb +0 -134
- data/lib/saucy/routing_extensions.rb +0 -116
- data/spec/dummy/db/migrate/20120206155222_add_subscription_token_to_canceled_accounts.rb +0 -5
- data/spec/environment.rb +0 -98
- data/spec/route_extensions_spec.rb +0 -51
- data/spec/scaffold/config/database.yml +0 -6
- data/spec/scaffold/config/routes.rb +0 -5
- data/spec/scaffold/views/layouts/application.html.erb +0 -1
data/{lib/generators/saucy/features/templates/features → features/engine}/edit_profile.feature
RENAMED
File without changes
|
File without changes
|
File without changes
|
data/{lib/generators/saucy/features/templates/features → features/engine}/manage_account.feature
RENAMED
File without changes
|
data/{lib/generators/saucy/features/templates/features → features/engine}/manage_billing.feature
RENAMED
@@ -81,7 +81,7 @@ Feature: Manage Billing
|
|
81
81
|
|
82
82
|
Scenario: View past credit card charges
|
83
83
|
Given I have signed up as "joe@example.com"
|
84
|
-
And the following
|
84
|
+
And the following transactions exist for the "Test" account:
|
85
85
|
| status | amount | created_at |
|
86
86
|
| Settled | 20.00 | July 1, 2010 |
|
87
87
|
| Settled | 5.00 | August 1, 2010 |
|
data/{lib/generators/saucy/features/templates/features → features/engine}/manage_plan.feature
RENAMED
File without changes
|
data/{lib/generators/saucy/features/templates/features → features/engine}/manage_projects.feature
RENAMED
File without changes
|
data/{lib/generators/saucy/features/templates/features → features/engine}/manage_users.feature
RENAMED
File without changes
|
data/{lib/generators/saucy/features/templates/features → features/engine}/new_account.feature
RENAMED
File without changes
|
data/{lib/generators/saucy/features/templates/features → features/engine}/project_dropdown.feature
RENAMED
File without changes
|
File without changes
|
data/{lib/generators/saucy/features/templates/features → features/engine}/sign_up_coupon.feature
RENAMED
File without changes
|
data/{lib/generators/saucy/features/templates/features → features/engine}/sign_up_paid.feature
RENAMED
File without changes
|
data/{lib/generators/saucy/features/templates/features → features/engine}/trial_plans.feature
RENAMED
File without changes
|
@@ -0,0 +1,46 @@
|
|
1
|
+
@disable-bundler @generates-application
|
2
|
+
Feature: generate a saucy application and run rake
|
3
|
+
|
4
|
+
Background:
|
5
|
+
When I generate a new rails application
|
6
|
+
And I copy the locked Gemfile from this project
|
7
|
+
And I append to "Gemfile" with:
|
8
|
+
"""
|
9
|
+
gem "clearance", "~> 0.14.0"
|
10
|
+
gem "cucumber-rails"
|
11
|
+
gem "selenium-webdriver", "~> 2.16.0"
|
12
|
+
gem "capybara"
|
13
|
+
gem "factory_girl_rails"
|
14
|
+
gem "dynamic_form"
|
15
|
+
gem "database_cleaner"
|
16
|
+
gem "formtastic", "~> 1.2.4"
|
17
|
+
gem "rspec-rails"
|
18
|
+
gem "bourne"
|
19
|
+
gem "shoulda-matchers"
|
20
|
+
gem "launchy"
|
21
|
+
gem "timecop"
|
22
|
+
gem "jquery-rails"
|
23
|
+
gem "minitest", "~> 2.6.1", :platforms => :ruby_19
|
24
|
+
gem "fake_braintree", "~> 0.2.0"
|
25
|
+
"""
|
26
|
+
When I add the "saucy" gem from this project as a dependency
|
27
|
+
And I successfully run `bundle install --local`
|
28
|
+
And I bootstrap the application for clearance
|
29
|
+
And I bootstrap the application for saucy
|
30
|
+
|
31
|
+
Scenario: generate a saucy application and run rake
|
32
|
+
When I run all cucumber scenarios
|
33
|
+
Then all cucumber scenarios should have passed
|
34
|
+
And all generators should have run successfully
|
35
|
+
|
36
|
+
Scenario: A new saucy app with custom views
|
37
|
+
When I successfully run `rails generate saucy:views`
|
38
|
+
And I give a more detailed new account message
|
39
|
+
And I run cucumber scenarios for customizations
|
40
|
+
Then all cucumber scenarios should have passed
|
41
|
+
And all generators should have run successfully
|
42
|
+
|
43
|
+
Scenario: A new saucy app with custom layouts
|
44
|
+
When I add a custom layout to the accounts index
|
45
|
+
And I run cucumber scenarios for customizations
|
46
|
+
Then all cucumber scenarios should have passed
|
@@ -43,3 +43,126 @@ When /^I configure "([^"]*)" as the root route$/ do |action|
|
|
43
43
|
/(routes\.draw do)/,
|
44
44
|
"\\1\nroot :to => '#{action}'"
|
45
45
|
end
|
46
|
+
|
47
|
+
# Existing users
|
48
|
+
|
49
|
+
Given /^(?:I am|I have|I) signed up (?:as|with) "(.*)"$/ do |email|
|
50
|
+
Factory(:user, :email => email)
|
51
|
+
end
|
52
|
+
|
53
|
+
Given /^a user "([^"]*)" exists without a salt, remember token, or password$/ do |email|
|
54
|
+
user = Factory(:user, :email => email)
|
55
|
+
sql = "update users set salt = NULL, encrypted_password = NULL, remember_token = NULL where id = #{user.id}"
|
56
|
+
ActiveRecord::Base.connection.update(sql)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Sign up
|
60
|
+
|
61
|
+
When /^I sign up (?:with|as) "(.*)" and "(.*)"$/ do |email, password|
|
62
|
+
visit sign_up_path
|
63
|
+
page.should have_css("input[type='email']")
|
64
|
+
|
65
|
+
fill_in "Email", :with => email
|
66
|
+
fill_in "Password", :with => password
|
67
|
+
click_button "Sign up"
|
68
|
+
end
|
69
|
+
|
70
|
+
# Sign in
|
71
|
+
|
72
|
+
Given /^I sign in$/ do
|
73
|
+
email = Factory.next(:email)
|
74
|
+
steps %{
|
75
|
+
I have signed up with "#{email}"
|
76
|
+
I sign in with "#{email}"
|
77
|
+
}
|
78
|
+
end
|
79
|
+
|
80
|
+
When /^I sign in (?:with|as) "([^"]*)"$/ do |email|
|
81
|
+
When %{I sign in with "#{email}" and "password"}
|
82
|
+
end
|
83
|
+
|
84
|
+
When /^I sign in (?:with|as) "([^"]*)" and "([^"]*)"$/ do |email, password|
|
85
|
+
visit sign_in_path
|
86
|
+
page.should have_css("input[type='email']")
|
87
|
+
|
88
|
+
fill_in "Email", :with => email
|
89
|
+
fill_in "Password", :with => password
|
90
|
+
click_button "Sign in"
|
91
|
+
end
|
92
|
+
|
93
|
+
# Sign out
|
94
|
+
|
95
|
+
When "I sign out" do
|
96
|
+
visit "/"
|
97
|
+
click_link "Sign out"
|
98
|
+
end
|
99
|
+
|
100
|
+
# Reset password
|
101
|
+
|
102
|
+
When /^I reset the password for "(.*)"$/ do |email|
|
103
|
+
visit new_password_path
|
104
|
+
page.should have_css("input[type='email']")
|
105
|
+
|
106
|
+
fill_in "Email address", :with => email
|
107
|
+
click_button "Reset password"
|
108
|
+
end
|
109
|
+
|
110
|
+
Then /^instructions for changing my password are emailed to "(.*)"$/ do |email|
|
111
|
+
page.should have_content("instructions for changing your password")
|
112
|
+
|
113
|
+
user = User.find_by_email!(email)
|
114
|
+
assert !user.confirmation_token.blank?
|
115
|
+
assert !ActionMailer::Base.deliveries.empty?
|
116
|
+
result = ActionMailer::Base.deliveries.any? do |email|
|
117
|
+
email.to == [user.email] &&
|
118
|
+
email.subject =~ /password/i &&
|
119
|
+
email.body =~ /#{user.confirmation_token}/
|
120
|
+
end
|
121
|
+
assert result
|
122
|
+
end
|
123
|
+
|
124
|
+
When /^I follow the password reset link sent to "(.*)"$/ do |email|
|
125
|
+
user = User.find_by_email!(email)
|
126
|
+
visit edit_user_password_path(:user_id => user,
|
127
|
+
:token => user.confirmation_token)
|
128
|
+
end
|
129
|
+
|
130
|
+
When /^I change the password of "(.*)" without token$/ do |email|
|
131
|
+
user = User.find_by_email!(email)
|
132
|
+
visit edit_user_password_path(:user_id => user)
|
133
|
+
end
|
134
|
+
|
135
|
+
When /^I update my password with "(.*)"$/ do |password|
|
136
|
+
fill_in "Choose password", :with => password
|
137
|
+
click_button "Save this password"
|
138
|
+
end
|
139
|
+
|
140
|
+
# Flashes
|
141
|
+
|
142
|
+
Then /^I am told email or password is bad$/ do
|
143
|
+
page.should have_content("Bad email or password")
|
144
|
+
end
|
145
|
+
|
146
|
+
Then /^I am told email is unknown$/ do
|
147
|
+
page.should have_content("Unknown email")
|
148
|
+
end
|
149
|
+
|
150
|
+
Then /^I am told to enter a valid email address$/ do
|
151
|
+
page.should have_content("Must be a valid email address")
|
152
|
+
end
|
153
|
+
|
154
|
+
Then /^I am told to enter a password$/ do
|
155
|
+
page.should have_content("Password can't be blank")
|
156
|
+
end
|
157
|
+
|
158
|
+
# Verification
|
159
|
+
|
160
|
+
Then /^I should be signed in$/ do
|
161
|
+
visit "/"
|
162
|
+
page.should have_content "Sign out"
|
163
|
+
end
|
164
|
+
|
165
|
+
Then /^I should be signed out$/ do
|
166
|
+
visit "/"
|
167
|
+
page.should have_content "Sign in"
|
168
|
+
end
|
File without changes
|
@@ -0,0 +1,24 @@
|
|
1
|
+
Given /^that the credit card "([^"]*)" is invalid$/ do |number|
|
2
|
+
FakeBraintree.registry.failures[number] = { "message" => "Credit card number is invalid.", "errors" => { "customer" => { "errors" => [], "credit-card" => { "errors" => [{ "message" => "Credit card number is invalid.", "code" => 81715, "attribute" => :number }] }}}}
|
3
|
+
end
|
4
|
+
|
5
|
+
Given /^that the credit card "([^"]*)" should not be honored$/ do |number|
|
6
|
+
FakeBraintree.registry.failures[number] = { "message" => "Do Not Honor", "code" => "2000", "status" => "processor_declined" }
|
7
|
+
end
|
8
|
+
|
9
|
+
Given /^the "([^"]*)" account is past due$/ do |account_name|
|
10
|
+
account = Account.find_by_name!(account_name)
|
11
|
+
account.update_attribute(:subscription_status, Braintree::Subscription::Status::PastDue)
|
12
|
+
end
|
13
|
+
|
14
|
+
Given /^the following transactions? exists? for the "([^"]*)" account:$/ do |account_name, table|
|
15
|
+
account = Account.find_by_name!(account_name)
|
16
|
+
subscription = FakeBraintree.registry.subscriptions[account.subscription_token]
|
17
|
+
subscription["transactions"] = []
|
18
|
+
table.hashes.each do |transaction|
|
19
|
+
subscription["transactions"] << FakeBraintree.generate_transaction({ :status => transaction["status"],
|
20
|
+
:amount => transaction["amount"],
|
21
|
+
:created_at => DateTime.parse(transaction["created_at"]),
|
22
|
+
:subscription_id => account.subscription_token })
|
23
|
+
end
|
24
|
+
end
|
File without changes
|
@@ -1,9 +1,9 @@
|
|
1
1
|
require 'rake'
|
2
2
|
|
3
|
-
|
3
|
+
class FakeRake
|
4
4
|
include Rake::DSL
|
5
5
|
|
6
|
-
def
|
6
|
+
def execute
|
7
7
|
old_rake = Rake.application
|
8
8
|
rake = Rake::Application.new
|
9
9
|
Rake.application = rake
|
@@ -14,10 +14,8 @@ module RakeHelpers
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
-
World(RakeHelpers)
|
18
|
-
|
19
17
|
When /^the daily Saucy jobs are processed$/ do
|
20
|
-
|
18
|
+
FakeRake.new.execute do |rake|
|
21
19
|
Saucy::Engine.load_tasks
|
22
20
|
rake['saucy:daily'].invoke
|
23
21
|
end
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -28,7 +28,7 @@ When /^I give a more detailed new account message$/ do
|
|
28
28
|
When I go to the sign up page for the "Free" plan
|
29
29
|
Then I should see "Please sign up now"
|
30
30
|
HERE
|
31
|
-
write_file('features/
|
31
|
+
write_file('features/customizations.feature', scenario)
|
32
32
|
end
|
33
33
|
|
34
34
|
When /^I add a custom layout to the accounts index$/ do
|
@@ -44,7 +44,7 @@ When /^I add a custom layout to the accounts index$/ do
|
|
44
44
|
/(class .* < Rails::Application)/,
|
45
45
|
"\\1\n#{layout_config}"
|
46
46
|
|
47
|
-
write_file('features/
|
47
|
+
write_file('features/customizations.feature', <<-SCENARIO)
|
48
48
|
Feature: The accounts index should have a custom layout
|
49
49
|
Scenario: Custom layout
|
50
50
|
Given I am signed up as "email@person.com"
|
@@ -62,12 +62,30 @@ When /^I add a custom layout to the accounts index$/ do
|
|
62
62
|
SCENARIO
|
63
63
|
end
|
64
64
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
65
|
+
Then /^all cucumber scenarios should have passed$/ do
|
66
|
+
assert_passing_with "passed"
|
67
|
+
assert_no_partial_output "failed", all_output
|
68
|
+
end
|
69
|
+
|
70
|
+
When /^I run all cucumber scenarios$/ do
|
71
|
+
run_simple "bundle exec rake cucumber"
|
72
|
+
end
|
73
|
+
|
74
|
+
When /^I run cucumber scenarios for customizations$/ do
|
75
|
+
run_simple "bundle exec cucumber features/customizations.feature"
|
76
|
+
end
|
77
|
+
|
78
|
+
Then /^all generators should have run successfully$/ do
|
79
|
+
assert_no_partial_output "Could not find generator", all_output
|
80
|
+
end
|
81
|
+
|
82
|
+
When /^I generate a new rails application$/ do
|
83
|
+
run_simple "bundle exec rails new testapp --skip-bundle"
|
84
|
+
cd "testapp"
|
69
85
|
end
|
70
86
|
|
71
|
-
Then /^
|
72
|
-
|
87
|
+
Then /^pause the page$/ do
|
88
|
+
puts
|
89
|
+
puts "Press enter to continue"
|
90
|
+
$stdin.gets
|
73
91
|
end
|
@@ -1,4 +1,7 @@
|
|
1
1
|
When /^I bootstrap the application for saucy$/ do
|
2
|
+
run_simple "rails generate saucy:install"
|
3
|
+
run_simple "rails generate saucy:features"
|
4
|
+
run_simple "bundle exec rake db:migrate db:test:prepare"
|
2
5
|
end
|
3
6
|
|
4
7
|
When /^I copy the locked Gemfile from this project$/ do
|
@@ -6,3 +9,5 @@ When /^I copy the locked Gemfile from this project$/ do
|
|
6
9
|
FileUtils.cp(File.join(PROJECT_ROOT, 'Gemfile.lock'), 'Gemfile.lock')
|
7
10
|
end
|
8
11
|
end
|
12
|
+
|
13
|
+
|
@@ -0,0 +1,253 @@
|
|
1
|
+
# TL;DR: YOU SHOULD DELETE THIS FILE
|
2
|
+
#
|
3
|
+
# This file was generated by Cucumber-Rails and is only here to get you a head start
|
4
|
+
# These step definitions are thin wrappers around the Capybara/Webrat API that lets you
|
5
|
+
# visit pages, interact with widgets and make assertions about page content.
|
6
|
+
#
|
7
|
+
# If you use these step definitions as basis for your features you will quickly end up
|
8
|
+
# with features that are:
|
9
|
+
#
|
10
|
+
# * Hard to maintain
|
11
|
+
# * Verbose to read
|
12
|
+
#
|
13
|
+
# A much better approach is to write your own higher level step definitions, following
|
14
|
+
# the advice in the following blog posts:
|
15
|
+
#
|
16
|
+
# * http://benmabey.com/2008/05/19/imperative-vs-declarative-scenarios-in-user-stories.html
|
17
|
+
# * http://dannorth.net/2011/01/31/whose-domain-is-it-anyway/
|
18
|
+
# * http://elabs.se/blog/15-you-re-cuking-it-wrong
|
19
|
+
#
|
20
|
+
|
21
|
+
|
22
|
+
require 'uri'
|
23
|
+
require 'cgi'
|
24
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "..", "support", "paths"))
|
25
|
+
|
26
|
+
module WithinHelpers
|
27
|
+
def with_scope(locator)
|
28
|
+
locator ? within(*selector_for(locator)) { yield } : yield
|
29
|
+
end
|
30
|
+
end
|
31
|
+
World(WithinHelpers)
|
32
|
+
|
33
|
+
# Single-line step scoper
|
34
|
+
When /^(.*) within (.*[^:])$/ do |step, parent|
|
35
|
+
with_scope(parent) { When step }
|
36
|
+
end
|
37
|
+
|
38
|
+
# Multi-line step scoper
|
39
|
+
When /^(.*) within (.*[^:]):$/ do |step, parent, table_or_string|
|
40
|
+
with_scope(parent) { When "#{step}:", table_or_string }
|
41
|
+
end
|
42
|
+
|
43
|
+
Given /^(?:|I )am on (.+)$/ do |page_name|
|
44
|
+
visit path_to(page_name)
|
45
|
+
end
|
46
|
+
|
47
|
+
When /^(?:|I )go to (.+)$/ do |page_name|
|
48
|
+
visit path_to(page_name)
|
49
|
+
end
|
50
|
+
|
51
|
+
When /^(?:|I )press "([^"]*)"$/ do |button|
|
52
|
+
click_button(button)
|
53
|
+
end
|
54
|
+
|
55
|
+
When /^(?:|I )follow "([^"]*)"$/ do |link|
|
56
|
+
click_link(link)
|
57
|
+
end
|
58
|
+
|
59
|
+
When /^(?:|I )fill in "([^"]*)" with "([^"]*)"$/ do |field, value|
|
60
|
+
fill_in(field, :with => value)
|
61
|
+
end
|
62
|
+
|
63
|
+
When /^(?:|I )fill in "([^"]*)" for "([^"]*)"$/ do |value, field|
|
64
|
+
fill_in(field, :with => value)
|
65
|
+
end
|
66
|
+
|
67
|
+
# Use this to fill in an entire form with data from a table. Example:
|
68
|
+
#
|
69
|
+
# When I fill in the following:
|
70
|
+
# | Account Number | 5002 |
|
71
|
+
# | Expiry date | 2009-11-01 |
|
72
|
+
# | Note | Nice guy |
|
73
|
+
# | Wants Email? | |
|
74
|
+
#
|
75
|
+
# TODO: Add support for checkbox, select or option
|
76
|
+
# based on naming conventions.
|
77
|
+
#
|
78
|
+
When /^(?:|I )fill in the following:$/ do |fields|
|
79
|
+
fields.rows_hash.each do |name, value|
|
80
|
+
When %{I fill in "#{name}" with "#{value}"}
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
When /^(?:|I )select "([^"]*)" from "([^"]*)"$/ do |value, field|
|
85
|
+
select(value, :from => field)
|
86
|
+
end
|
87
|
+
|
88
|
+
When /^(?:|I )check "([^"]*)"$/ do |field|
|
89
|
+
check(field)
|
90
|
+
end
|
91
|
+
|
92
|
+
When /^(?:|I )uncheck "([^"]*)"$/ do |field|
|
93
|
+
uncheck(field)
|
94
|
+
end
|
95
|
+
|
96
|
+
When /^(?:|I )choose "([^"]*)"$/ do |field|
|
97
|
+
choose(field)
|
98
|
+
end
|
99
|
+
|
100
|
+
When /^(?:|I )attach the file "([^"]*)" to "([^"]*)"$/ do |path, field|
|
101
|
+
attach_file(field, File.expand_path(path))
|
102
|
+
end
|
103
|
+
|
104
|
+
Then /^(?:|I )should see "([^"]*)"$/ do |text|
|
105
|
+
if page.respond_to? :should
|
106
|
+
page.should have_content(text)
|
107
|
+
else
|
108
|
+
assert page.has_content?(text)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
Then /^(?:|I )should see \/([^\/]*)\/$/ do |regexp|
|
113
|
+
regexp = Regexp.new(regexp)
|
114
|
+
|
115
|
+
if page.respond_to? :should
|
116
|
+
page.should have_xpath('//*', :text => regexp)
|
117
|
+
else
|
118
|
+
assert page.has_xpath?('//*', :text => regexp)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
Then /^(?:|I )should not see "([^"]*)"$/ do |text|
|
123
|
+
if page.respond_to? :should
|
124
|
+
page.should have_no_content(text)
|
125
|
+
else
|
126
|
+
assert page.has_no_content?(text)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
Then /^(?:|I )should not see \/([^\/]*)\/$/ do |regexp|
|
131
|
+
regexp = Regexp.new(regexp)
|
132
|
+
|
133
|
+
if page.respond_to? :should
|
134
|
+
page.should have_no_xpath('//*', :text => regexp)
|
135
|
+
else
|
136
|
+
assert page.has_no_xpath?('//*', :text => regexp)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
Then /^the "([^"]*)" field(?: within (.*))? should contain "([^"]*)"$/ do |field, parent, value|
|
141
|
+
with_scope(parent) do
|
142
|
+
field = find_field(field)
|
143
|
+
field_value = (field.tag_name == 'textarea') ? field.text : field.value
|
144
|
+
if field_value.respond_to? :should
|
145
|
+
field_value.should =~ /#{value}/
|
146
|
+
else
|
147
|
+
assert_match(/#{value}/, field_value)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
Then /^the "([^"]*)" field(?: within (.*))? should not contain "([^"]*)"$/ do |field, parent, value|
|
153
|
+
with_scope(parent) do
|
154
|
+
field = find_field(field)
|
155
|
+
field_value = (field.tag_name == 'textarea') ? field.text : field.value
|
156
|
+
if field_value.respond_to? :should_not
|
157
|
+
field_value.should_not =~ /#{value}/
|
158
|
+
else
|
159
|
+
assert_no_match(/#{value}/, field_value)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
Then /^the "([^"]*)" field should have the error "([^"]*)"$/ do |field, error_message|
|
165
|
+
element = find_field(field)
|
166
|
+
classes = element.find(:xpath, '..')[:class].split(' ')
|
167
|
+
|
168
|
+
form_for_input = element.find(:xpath, 'ancestor::form[1]')
|
169
|
+
using_formtastic = form_for_input[:class].include?('formtastic')
|
170
|
+
error_class = using_formtastic ? 'error' : 'field_with_errors'
|
171
|
+
|
172
|
+
if classes.respond_to? :should
|
173
|
+
classes.should include(error_class)
|
174
|
+
else
|
175
|
+
assert classes.include?(error_class)
|
176
|
+
end
|
177
|
+
|
178
|
+
if page.respond_to?(:should)
|
179
|
+
if using_formtastic
|
180
|
+
error_paragraph = element.find(:xpath, '../*[@class="inline-errors"][1]')
|
181
|
+
error_paragraph.should have_content(error_message)
|
182
|
+
else
|
183
|
+
page.should have_content("#{field.titlecase} #{error_message}")
|
184
|
+
end
|
185
|
+
else
|
186
|
+
if using_formtastic
|
187
|
+
error_paragraph = element.find(:xpath, '../*[@class="inline-errors"][1]')
|
188
|
+
assert error_paragraph.has_content?(error_message)
|
189
|
+
else
|
190
|
+
assert page.has_content?("#{field.titlecase} #{error_message}")
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
Then /^the "([^"]*)" field should have no error$/ do |field|
|
196
|
+
element = find_field(field)
|
197
|
+
classes = element.find(:xpath, '..')[:class].split(' ')
|
198
|
+
if classes.respond_to? :should
|
199
|
+
classes.should_not include('field_with_errors')
|
200
|
+
classes.should_not include('error')
|
201
|
+
else
|
202
|
+
assert !classes.include?('field_with_errors')
|
203
|
+
assert !classes.include?('error')
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
Then /^the "([^"]*)" checkbox(?: within (.*))? should be checked$/ do |label, parent|
|
208
|
+
with_scope(parent) do
|
209
|
+
field_checked = find_field(label)['checked']
|
210
|
+
if field_checked.respond_to? :should
|
211
|
+
field_checked.should be_true
|
212
|
+
else
|
213
|
+
assert field_checked
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
Then /^the "([^"]*)" checkbox(?: within (.*))? should not be checked$/ do |label, parent|
|
219
|
+
with_scope(parent) do
|
220
|
+
field_checked = find_field(label)['checked']
|
221
|
+
if field_checked.respond_to? :should
|
222
|
+
field_checked.should be_false
|
223
|
+
else
|
224
|
+
assert !field_checked
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
Then /^(?:|I )should be on (.+)$/ do |page_name|
|
230
|
+
current_path = URI.parse(current_url).path
|
231
|
+
if current_path.respond_to? :should
|
232
|
+
current_path.should == path_to(page_name)
|
233
|
+
else
|
234
|
+
assert_equal path_to(page_name), current_path
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
Then /^(?:|I )should have the following query string:$/ do |expected_pairs|
|
239
|
+
query = URI.parse(current_url).query
|
240
|
+
actual_params = query ? CGI.parse(query) : {}
|
241
|
+
expected_params = {}
|
242
|
+
expected_pairs.rows_hash.each_pair{|k,v| expected_params[k] = v.split(',')}
|
243
|
+
|
244
|
+
if actual_params.respond_to? :should
|
245
|
+
actual_params.should == expected_params
|
246
|
+
else
|
247
|
+
assert_equal expected_params, actual_params
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
Then /^show me the page$/ do
|
252
|
+
save_and_open_page
|
253
|
+
end
|