cucumber_scaffold 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Manifest +12 -0
- data/README.rdoc +226 -0
- data/Rakefile +13 -0
- data/TODO +11 -0
- data/cucumber_scaffold.gemspec +30 -0
- data/lib/generators/cucumber_scaffold/feature/USAGE +22 -0
- data/lib/generators/cucumber_scaffold/feature/feature_generator.rb +194 -0
- data/lib/generators/cucumber_scaffold/feature/templates/feature.feature +282 -0
- data/lib/generators/cucumber_scaffold/feature/templates/steps.rb +40 -0
- data/lib/generators/cucumber_scaffold/install/USAGE +9 -0
- data/lib/generators/cucumber_scaffold/install/install_generator.rb +13 -0
- data/lib/generators/cucumber_scaffold/install/templates/shared/web_steps_additional.rb +38 -0
- metadata +92 -0
data/Manifest
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
Manifest
|
2
|
+
README.rdoc
|
3
|
+
Rakefile
|
4
|
+
TODO
|
5
|
+
cucumber_scaffold.gemspec
|
6
|
+
lib/generators/cucumber_scaffold/feature/USAGE
|
7
|
+
lib/generators/cucumber_scaffold/feature/feature_generator.rb
|
8
|
+
lib/generators/cucumber_scaffold/feature/templates/feature.feature
|
9
|
+
lib/generators/cucumber_scaffold/feature/templates/steps.rb
|
10
|
+
lib/generators/cucumber_scaffold/install/USAGE
|
11
|
+
lib/generators/cucumber_scaffold/install/install_generator.rb
|
12
|
+
lib/generators/cucumber_scaffold/install/templates/shared/web_steps_additional.rb
|
data/README.rdoc
ADDED
@@ -0,0 +1,226 @@
|
|
1
|
+
== Installation
|
2
|
+
|
3
|
+
$ gem install cucumber_scaffold
|
4
|
+
|
5
|
+
== Usage
|
6
|
+
|
7
|
+
$ rails generate cucumber_scaffold:install
|
8
|
+
$ rails generate cucumber_scaffold:feature Post name:string body:text
|
9
|
+
|
10
|
+
== Sample Output
|
11
|
+
|
12
|
+
# Generated by cucumber_scaffold - http://github.com/andyw8/cucumber_scaffold
|
13
|
+
|
14
|
+
Feature: Manage Posts
|
15
|
+
In order to [goal]
|
16
|
+
[stakeholder]
|
17
|
+
wants [behaviour]
|
18
|
+
|
19
|
+
@index
|
20
|
+
Scenario: List all posts
|
21
|
+
Given the following posts:
|
22
|
+
| name | body |
|
23
|
+
| name 1 | body 1 |
|
24
|
+
| name 2 | body 2 |
|
25
|
+
| name 3 | body 3 |
|
26
|
+
When I go to the posts page
|
27
|
+
Then I should see the following posts:
|
28
|
+
| Name | Body |
|
29
|
+
| name 1 | body 1 |
|
30
|
+
| name 2 | body 2 |
|
31
|
+
| name 3 | body 3 |
|
32
|
+
|
33
|
+
@show
|
34
|
+
Scenario: View a post
|
35
|
+
Given the following post:
|
36
|
+
| name | name 1 |
|
37
|
+
| body | body 1 |
|
38
|
+
When I go to the page for that post
|
39
|
+
Then I should see the following post:
|
40
|
+
| Name: | name 1 |
|
41
|
+
| Body: | body 1 |
|
42
|
+
|
43
|
+
@edit
|
44
|
+
Scenario: Edit a post
|
45
|
+
Given the following post:
|
46
|
+
| name | name 1 |
|
47
|
+
| body | body 1 |
|
48
|
+
When I go to the edit page for that post
|
49
|
+
Then I should see the following form field values:
|
50
|
+
| Name | name 1 |
|
51
|
+
| Body | body 1 |
|
52
|
+
|
53
|
+
@index @destroy
|
54
|
+
Scenario: Delete a post via the index page
|
55
|
+
Given the following posts:
|
56
|
+
| name | body |
|
57
|
+
| name 1 | body 1 |
|
58
|
+
| name 2 | body 2 |
|
59
|
+
| name 3 | body 3 |
|
60
|
+
When I go to the posts page
|
61
|
+
And I click "Destroy" in the 2nd row
|
62
|
+
Then I should see the following posts:
|
63
|
+
| Name | Body |
|
64
|
+
| name 1 | body 1 |
|
65
|
+
| name 3 | body 3 |
|
66
|
+
And I should be on the posts page
|
67
|
+
|
68
|
+
@new @create @show
|
69
|
+
Scenario: Create a new post
|
70
|
+
Pending
|
71
|
+
# Given I am on the new post page
|
72
|
+
# When I fill in the following:
|
73
|
+
# | Name | name 1 |
|
74
|
+
# | Body | body 1 |
|
75
|
+
# And I press "Create"
|
76
|
+
# Then I should see "Post was successfully created."
|
77
|
+
# And I should see the following post:
|
78
|
+
# | Name: | name 1 |
|
79
|
+
# | Body: | body 1 |
|
80
|
+
#
|
81
|
+
# In order to confirm that the user is redirected to the correct page
|
82
|
+
# after create, you'll need to add an entry to paths.rb to uniquely
|
83
|
+
# find a post, e.g.:
|
84
|
+
#
|
85
|
+
# when /page for the post with name "([^"]*)"$/
|
86
|
+
# conditions = { :conditions => {:name => $1} }
|
87
|
+
# matches = Post.all(conditions)
|
88
|
+
# if matches.size == 0
|
89
|
+
# raise "Could not find any posts using criteria #{conditions.inspect}"
|
90
|
+
# elsif matches.size > 1
|
91
|
+
# raise "Could not find a unique post using criteria #{conditions.inspect} (#{matches.size} matches)"
|
92
|
+
# end
|
93
|
+
# post_path(matches.first)
|
94
|
+
#
|
95
|
+
# Then add a step such as this to the scenario:
|
96
|
+
#
|
97
|
+
# And I should be on the page for the post with name "..."
|
98
|
+
|
99
|
+
@new @create
|
100
|
+
Scenario: Attempt to create a new post with invalid input
|
101
|
+
Pending
|
102
|
+
# You should use this scenario as the basis for scenarios involving ActiveRecord validations, or delete it if it's not required
|
103
|
+
# Given I am on the new post page
|
104
|
+
# When I fill in the following:
|
105
|
+
# | Name | name 1 |
|
106
|
+
# | Body | body 1 |
|
107
|
+
# And I press "Create"
|
108
|
+
# Then I should see "prohibited this post from being saved:"
|
109
|
+
#
|
110
|
+
# [You should add checks for specific errors here. It may be appropriate to add extra scenarios.]
|
111
|
+
#
|
112
|
+
# And I should be on the posts page
|
113
|
+
# And I should see the following form field values:
|
114
|
+
# | Name: | name 1 |
|
115
|
+
# | Body: | body 1 |
|
116
|
+
|
117
|
+
@edit @update
|
118
|
+
Scenario: Attempt to update a post with invalid input
|
119
|
+
Pending
|
120
|
+
# You should use this scenario as the basis for scenarios involving ActiveRecord validations, or delete it if it's not required
|
121
|
+
# Given a post exists
|
122
|
+
# When I go to the edit page for that post
|
123
|
+
# And I fill in the following:
|
124
|
+
# | Name | name 1 |
|
125
|
+
# | Body | body 1 |
|
126
|
+
# And I press "Update"
|
127
|
+
# Then I should see "prohibited this post from being saved:"
|
128
|
+
#
|
129
|
+
# [You should add checks for specific errors here. It may be appropriate to add extra scenarios.]
|
130
|
+
#
|
131
|
+
# And I should be on the page for that post
|
132
|
+
# And I should see the following form field values:
|
133
|
+
# | Name: | name 1 |
|
134
|
+
# | Body: | body 1 |
|
135
|
+
|
136
|
+
@edit @update @show
|
137
|
+
Scenario: Update a post
|
138
|
+
Given a post exists
|
139
|
+
When I go to the edit page for that post
|
140
|
+
And I fill in the following:
|
141
|
+
| Name | name 1 updated |
|
142
|
+
| Body | body 1 updated |
|
143
|
+
And I press "Update"
|
144
|
+
Then I should be on the page for that post
|
145
|
+
And I should see "Post was successfully updated."
|
146
|
+
And I should see the following post:
|
147
|
+
| Name: | name 1 updated |
|
148
|
+
| Body: | body 1 updated |
|
149
|
+
|
150
|
+
@index @new
|
151
|
+
Scenario: Navigate from the posts page to the new post page
|
152
|
+
Given I am on the posts page
|
153
|
+
When I follow "New Post"
|
154
|
+
Then I should be on the new post page
|
155
|
+
|
156
|
+
@index @show
|
157
|
+
Scenario: Navigate from posts page to the show post page
|
158
|
+
Given the following posts:
|
159
|
+
| name | body |
|
160
|
+
| name 1 | body 1 |
|
161
|
+
| name 2 | body 2 |
|
162
|
+
| name 3 | body 3 |
|
163
|
+
When I go to the posts page
|
164
|
+
And I click "Show" in the 2nd row
|
165
|
+
Then I should be on the page for the 2nd post
|
166
|
+
|
167
|
+
@index @edit
|
168
|
+
Scenario: Navigate from posts page to the edit post page
|
169
|
+
Given the following posts:
|
170
|
+
| name | body |
|
171
|
+
| name 1 | body 1 |
|
172
|
+
| name 2 | body 2 |
|
173
|
+
| name 3 | body 3 |
|
174
|
+
When I go to the posts page
|
175
|
+
And I click "Edit" in the 2nd row
|
176
|
+
Then I should be on the edit page for the 2nd post
|
177
|
+
|
178
|
+
@new @index
|
179
|
+
Scenario: Navigate from new post page to posts page
|
180
|
+
Given I am on the new post page
|
181
|
+
When I follow "Back"
|
182
|
+
Then I should be on the posts page
|
183
|
+
|
184
|
+
@edit @show
|
185
|
+
Scenario: Navigate from the edit post page to the show post page
|
186
|
+
Given a post exists
|
187
|
+
When I go to the edit page for that post
|
188
|
+
And I follow "Show"
|
189
|
+
Then I should be on the page for that post
|
190
|
+
|
191
|
+
@edit @index
|
192
|
+
Scenario: Navigate from edit post page to the posts page
|
193
|
+
Given a post exists
|
194
|
+
When I go to the edit page for that post
|
195
|
+
And I follow "Back"
|
196
|
+
Then I should be on the posts page
|
197
|
+
|
198
|
+
@show @edit
|
199
|
+
Scenario: Navigate from show post page to edit post page
|
200
|
+
Given a post exists
|
201
|
+
When I go to the page for that post
|
202
|
+
And I follow "Edit"
|
203
|
+
Then I should be on the edit page for that post
|
204
|
+
|
205
|
+
@show @index
|
206
|
+
Scenario: Navigate from show post page to posts page
|
207
|
+
Given a post exists
|
208
|
+
And I am on the page for that post
|
209
|
+
And I follow "Back"
|
210
|
+
Then I should be on the posts page
|
211
|
+
|
212
|
+
@index
|
213
|
+
Scenario: Posts page title
|
214
|
+
When I go to the posts page
|
215
|
+
Then the heading should be "Listing posts"
|
216
|
+
|
217
|
+
@new
|
218
|
+
Scenario: New post page title
|
219
|
+
When I go to the new post page
|
220
|
+
Then the heading should be "New post"
|
221
|
+
|
222
|
+
@edit
|
223
|
+
Scenario: Edit post page title
|
224
|
+
Given a post exists
|
225
|
+
When I go to the edit page for that post
|
226
|
+
Then the heading should be "Editing post"
|
data/Rakefile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'echoe'
|
4
|
+
|
5
|
+
Echoe.new('cucumber_scaffold', '0.1.0') do |p|
|
6
|
+
p.description = "Generate scaffolding for Cucumber features and steps definitions"
|
7
|
+
p.url = "http://github.com/andyw8/cucumber_scaffold"
|
8
|
+
p.author = "Andy Waite"
|
9
|
+
p.email = "andy@andywaite.com"
|
10
|
+
p.development_dependencies = []
|
11
|
+
end
|
12
|
+
|
13
|
+
Dir["#{File.dirname(__FILE__)}/tasks/*.rake"].sort.each { |ext| load ext }
|
data/TODO
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
* Test with webrat as well as capybara
|
2
|
+
* Test with Rails 2.x
|
3
|
+
* Test with Formtastic
|
4
|
+
* Test with inherited_resources
|
5
|
+
* Test with with inherited_resources_views
|
6
|
+
* Add support for booleans (checkboxes)
|
7
|
+
* Add support for date/time fields
|
8
|
+
* Add support for belongs_to associations
|
9
|
+
* Test for model names containing more than one word (e.g. DocumentCategory)
|
10
|
+
* Add automated test suite
|
11
|
+
* Prevent excess whitespace in generated files
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{cucumber_scaffold}
|
5
|
+
s.version = "0.1.0"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Andy Waite"]
|
9
|
+
s.date = %q{2010-11-06}
|
10
|
+
s.description = %q{Generate scaffolding for Cucumber features and steps definitions}
|
11
|
+
s.email = %q{andy@andywaite.com}
|
12
|
+
s.extra_rdoc_files = ["README.rdoc", "TODO", "lib/generators/cucumber_scaffold/feature/USAGE", "lib/generators/cucumber_scaffold/feature/feature_generator.rb", "lib/generators/cucumber_scaffold/feature/templates/feature.feature", "lib/generators/cucumber_scaffold/feature/templates/steps.rb", "lib/generators/cucumber_scaffold/install/USAGE", "lib/generators/cucumber_scaffold/install/install_generator.rb", "lib/generators/cucumber_scaffold/install/templates/shared/web_steps_additional.rb"]
|
13
|
+
s.files = ["Manifest", "README.rdoc", "Rakefile", "TODO", "cucumber_scaffold.gemspec", "lib/generators/cucumber_scaffold/feature/USAGE", "lib/generators/cucumber_scaffold/feature/feature_generator.rb", "lib/generators/cucumber_scaffold/feature/templates/feature.feature", "lib/generators/cucumber_scaffold/feature/templates/steps.rb", "lib/generators/cucumber_scaffold/install/USAGE", "lib/generators/cucumber_scaffold/install/install_generator.rb", "lib/generators/cucumber_scaffold/install/templates/shared/web_steps_additional.rb"]
|
14
|
+
s.homepage = %q{http://github.com/andyw8/cucumber_scaffold}
|
15
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Cucumber_scaffold", "--main", "README.rdoc"]
|
16
|
+
s.require_paths = ["lib"]
|
17
|
+
s.rubyforge_project = %q{cucumber_scaffold}
|
18
|
+
s.rubygems_version = %q{1.3.7}
|
19
|
+
s.summary = %q{Generate scaffolding for Cucumber features and steps definitions}
|
20
|
+
|
21
|
+
if s.respond_to? :specification_version then
|
22
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
23
|
+
s.specification_version = 3
|
24
|
+
|
25
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
26
|
+
else
|
27
|
+
end
|
28
|
+
else
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
Description:
|
2
|
+
Scaffolding for Cucumber features
|
3
|
+
|
4
|
+
Example:
|
5
|
+
|
6
|
+
rails generate cucumber_scaffold_feature Post title:string body:text
|
7
|
+
|
8
|
+
This will create:
|
9
|
+
features/manage_posts.rb
|
10
|
+
features/step_definitions/post_steps.rb
|
11
|
+
|
12
|
+
and will modify:
|
13
|
+
features/support/paths.rb
|
14
|
+
|
15
|
+
Options:
|
16
|
+
|
17
|
+
--nifty
|
18
|
+
Generate features and steps which match the scaffold created by nifty-generators
|
19
|
+
( https://github.com/ryanb/nifty-generators )
|
20
|
+
|
21
|
+
--tags
|
22
|
+
Include Cucumbers @tags matching each scenario to one or more controller actions
|
@@ -0,0 +1,194 @@
|
|
1
|
+
module CucumberScaffold
|
2
|
+
class FeatureGenerator < Rails::Generators::NamedBase
|
3
|
+
|
4
|
+
INDENT = " "
|
5
|
+
LINE_BREAK_WITH_INDENT = "\n#{INDENT}"
|
6
|
+
LINE_BREAK_WITH_INDENT_COMMENTED = "\n#{INDENT}# "
|
7
|
+
|
8
|
+
argument :model_name, :type => :string
|
9
|
+
|
10
|
+
source_root File.expand_path('../templates', __FILE__)
|
11
|
+
|
12
|
+
def initialize(args, *options)
|
13
|
+
# copied setup from
|
14
|
+
# http://apidock.com/rails/Rails/Generators/NamedBase/new/class
|
15
|
+
args[0] = args[0].dup if args[0].is_a?(String) && args[0].frozen?
|
16
|
+
super
|
17
|
+
assign_names!(self.name)
|
18
|
+
parse_attributes! if respond_to?(:attributes)
|
19
|
+
args.shift
|
20
|
+
@args = args
|
21
|
+
end
|
22
|
+
|
23
|
+
def do_it
|
24
|
+
@attributes = []
|
25
|
+
@args.each do |param_pair|
|
26
|
+
name, type = param_pair.split(':')
|
27
|
+
@attributes << { name => type }
|
28
|
+
end
|
29
|
+
|
30
|
+
template('feature.feature', "features/manage_#{plural}.feature")
|
31
|
+
template('steps.rb', "features/step_definitions/#{singular}_steps.rb")
|
32
|
+
|
33
|
+
extra_paths = <<EOF
|
34
|
+
when /edit page for that #{singular}/
|
35
|
+
edit_#{singular}_path(@#{singular})
|
36
|
+
when /page for that #{singular}/
|
37
|
+
raise 'no #{singular}' unless @#{singular}
|
38
|
+
#{singular}_path(@#{singular})
|
39
|
+
when /edit page for the (\\d+)(?:st|nd|rd|th) #{singular}/
|
40
|
+
raise 'no #{plural}' unless @#{plural}
|
41
|
+
nth_#{singular} = @#{plural}[$1.to_i - 1]
|
42
|
+
edit_#{singular}_path(nth_#{singular})
|
43
|
+
when /page for the (\\d+)(?:st|nd|rd|th) #{singular}/
|
44
|
+
raise 'no #{plural}' unless @#{plural}
|
45
|
+
nth_#{singular} = @#{plural}[$1.to_i - 1]
|
46
|
+
#{singular}_path(nth_#{singular})
|
47
|
+
EOF
|
48
|
+
|
49
|
+
gsub_file 'features/support/paths.rb', /'\/'/mi do |match|
|
50
|
+
"#{match}\n" + extra_paths
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def generated_by
|
58
|
+
'# Generated by cucumber_scaffold - http://github.com/andyw8/cucumber_scaffold'
|
59
|
+
end
|
60
|
+
|
61
|
+
def nifty?
|
62
|
+
options[:nifty].present?
|
63
|
+
end
|
64
|
+
|
65
|
+
def singular
|
66
|
+
name.underscore.downcase
|
67
|
+
end
|
68
|
+
|
69
|
+
def plural
|
70
|
+
singular.pluralize
|
71
|
+
end
|
72
|
+
|
73
|
+
def singular_title
|
74
|
+
singular.titleize
|
75
|
+
end
|
76
|
+
|
77
|
+
def plural_title
|
78
|
+
plural.titleize
|
79
|
+
end
|
80
|
+
|
81
|
+
def activerecord_table_header_row
|
82
|
+
make_row(attribute_names)
|
83
|
+
end
|
84
|
+
|
85
|
+
def html_table_header_row
|
86
|
+
make_row(attribute_names.map(&:titleize))
|
87
|
+
end
|
88
|
+
|
89
|
+
def attribute_names
|
90
|
+
@attributes.collect {|a| a.first[0]}
|
91
|
+
end
|
92
|
+
|
93
|
+
def html_single_resource(updated=nil, commented=nil)
|
94
|
+
lines = []
|
95
|
+
@attributes.each do |pair|
|
96
|
+
attribute_name = pair.first[0]
|
97
|
+
attribute_value = pair.first[1]
|
98
|
+
lines << "| #{attribute_name.titleize}: | #{default_value(attribute_name, attribute_value, updated)} |"
|
99
|
+
end
|
100
|
+
lines.join(commented ? LINE_BREAK_WITH_INDENT_COMMENTED : LINE_BREAK_WITH_INDENT)
|
101
|
+
end
|
102
|
+
|
103
|
+
def form_single_resource_commented
|
104
|
+
form_single_resource(false, true)
|
105
|
+
end
|
106
|
+
|
107
|
+
def html_single_resource_commented
|
108
|
+
html_single_resource(false, true)
|
109
|
+
end
|
110
|
+
|
111
|
+
def form_single_resource(updated=nil, commented=nil)
|
112
|
+
lines = []
|
113
|
+
@attributes.each do |pair|
|
114
|
+
attribute_name = pair.first[0]
|
115
|
+
attribute_value = pair.first[1]
|
116
|
+
lines << "| #{attribute_name.titleize} | #{default_value(attribute_name, attribute_value, updated)} |"
|
117
|
+
end
|
118
|
+
result = lines.join(commented ? LINE_BREAK_WITH_INDENT_COMMENTED : LINE_BREAK_WITH_INDENT)
|
119
|
+
end
|
120
|
+
|
121
|
+
def activerecord_single_resource(updated=nil)
|
122
|
+
lines = []
|
123
|
+
@attributes.each do |pair|
|
124
|
+
attribute_name = pair.first[0]
|
125
|
+
attribute_value = pair.first[1]
|
126
|
+
lines << "| #{attribute_name} | #{default_value(attribute_name, attribute_value, updated)} |"
|
127
|
+
end
|
128
|
+
lines.join(LINE_BREAK_WITH_INDENT)
|
129
|
+
end
|
130
|
+
|
131
|
+
def html_resources
|
132
|
+
[html_table_header_row,
|
133
|
+
html_table_row(1),
|
134
|
+
html_table_row(2),
|
135
|
+
html_table_row(3)].join(LINE_BREAK_WITH_INDENT)
|
136
|
+
end
|
137
|
+
|
138
|
+
def activerecord_resources
|
139
|
+
[activerecord_table_header_row,
|
140
|
+
activerecord_table_row(1),
|
141
|
+
activerecord_table_row(2),
|
142
|
+
activerecord_table_row(3)].join(LINE_BREAK_WITH_INDENT)
|
143
|
+
end
|
144
|
+
|
145
|
+
def activerecord_single_resource_updated
|
146
|
+
activerecord_single_resource(true)
|
147
|
+
end
|
148
|
+
|
149
|
+
def form_single_resource_updated
|
150
|
+
form_single_resource(true)
|
151
|
+
end
|
152
|
+
|
153
|
+
def html_single_resource_updated
|
154
|
+
html_single_resource(true)
|
155
|
+
end
|
156
|
+
|
157
|
+
def default_value(attribute_name, attribute_type, updated=false, index=1)
|
158
|
+
# TODO use an options hash instead of all these arguments
|
159
|
+
if ['string', 'text'].include?(attribute_type)
|
160
|
+
result = "#{attribute_name} #{index}"
|
161
|
+
result += ' updated' if updated
|
162
|
+
elsif attribute_type == 'integer'
|
163
|
+
result = 10 + index
|
164
|
+
result = -result if updated
|
165
|
+
else
|
166
|
+
raise "Cannot create default value for attribute type '#{attribute_type}'"
|
167
|
+
end
|
168
|
+
result
|
169
|
+
end
|
170
|
+
|
171
|
+
def activerecord_table_row(n)
|
172
|
+
data = []
|
173
|
+
@attributes.each do |attribute|
|
174
|
+
attribute_name = attribute.first[0]
|
175
|
+
attribute_type = attribute.first[1]
|
176
|
+
data << default_value(attribute_name, attribute_type, false, n)
|
177
|
+
end
|
178
|
+
make_row(data)
|
179
|
+
end
|
180
|
+
|
181
|
+
def html_table_row(n)
|
182
|
+
activerecord_table_row(n)
|
183
|
+
end
|
184
|
+
|
185
|
+
def tags(tags)
|
186
|
+
tags
|
187
|
+
end
|
188
|
+
|
189
|
+
def make_row(data)
|
190
|
+
"| #{data.join(' | ')} |"
|
191
|
+
end
|
192
|
+
|
193
|
+
end
|
194
|
+
end
|
@@ -0,0 +1,282 @@
|
|
1
|
+
<%= generated_by %>
|
2
|
+
<%
|
3
|
+
update_button_title = 'Update'
|
4
|
+
create_button_title = 'Create'
|
5
|
+
|
6
|
+
if nifty?
|
7
|
+
successful_update_message = "Successfully updated #{singular}."
|
8
|
+
successful_create_message = "Successfully created #{singular}."
|
9
|
+
successful_destroy_message = "Successfully destroyed #{singular}."
|
10
|
+
new_heading = "New #{singular_title}"
|
11
|
+
edit_heading = "Edit #{singular_title}"
|
12
|
+
index_heading = plural_title
|
13
|
+
show_heading = singular_title
|
14
|
+
new_title = new_heading
|
15
|
+
edit_title = edit_heading
|
16
|
+
index_title = index_heading
|
17
|
+
show_title = show_heading
|
18
|
+
back_to_all = 'Back to List'
|
19
|
+
problems_intro = 'Correct the following errors and try again.'
|
20
|
+
else
|
21
|
+
problems_intro =
|
22
|
+
successful_update_message = "#{singular_title} was successfully updated."
|
23
|
+
successful_create_message = "#{singular_title} was successfully created."
|
24
|
+
index_heading = "Listing #{plural}"
|
25
|
+
edit_heading = "Editing #{singular}"
|
26
|
+
new_heading = "New #{singular}"
|
27
|
+
back_to_all = 'Back'
|
28
|
+
problems_intro = "prohibited this post from being saved:"
|
29
|
+
end
|
30
|
+
|
31
|
+
pending_explanation_1 = "You should use this scenario as the basis for scenarios involving ActiveRecord validations, or delete it if it's not required"
|
32
|
+
pending_explanation_2 = "[You should add checks for specific errors here. It may be appropriate to add extra scenarios.]"
|
33
|
+
-%>
|
34
|
+
|
35
|
+
Feature: Manage <%= plural_title %>
|
36
|
+
In order to [goal]
|
37
|
+
[stakeholder]
|
38
|
+
wants [behaviour]
|
39
|
+
|
40
|
+
<%= tags('@index') %>
|
41
|
+
Scenario: List all <%= plural %>
|
42
|
+
Given the following <%= plural %>:
|
43
|
+
<%= activerecord_table_header_row %>
|
44
|
+
<%= activerecord_table_row(1) %>
|
45
|
+
<%= activerecord_table_row(2) %>
|
46
|
+
<%= activerecord_table_row(3) %>
|
47
|
+
When I go to the <%= plural %> page
|
48
|
+
Then I should see the following <%= plural %>:
|
49
|
+
<%= html_table_header_row %>
|
50
|
+
<%= html_table_row(1) %>
|
51
|
+
<%= html_table_row(2) %>
|
52
|
+
<%= html_table_row(3) %>
|
53
|
+
|
54
|
+
<%= tags('@show') %>
|
55
|
+
Scenario: View a <%= singular %>
|
56
|
+
Given the following <%= singular %>:
|
57
|
+
<%= activerecord_single_resource %>
|
58
|
+
When I go to the page for that <%= singular %>
|
59
|
+
Then I should see the following <%= singular %>:
|
60
|
+
<%= html_single_resource %>
|
61
|
+
|
62
|
+
<%= tags('@edit') %>
|
63
|
+
Scenario: Edit a <%= singular %>
|
64
|
+
Given the following <%= singular %>:
|
65
|
+
<%= activerecord_single_resource %>
|
66
|
+
When I go to the edit page for that <%= singular %>
|
67
|
+
Then I should see the following form field values:
|
68
|
+
<%= form_single_resource %>
|
69
|
+
|
70
|
+
<%= tags('@index @destroy') %>
|
71
|
+
Scenario: Delete a <%= singular %> via the index page
|
72
|
+
Given the following <%= plural %>:
|
73
|
+
<%= activerecord_table_header_row %>
|
74
|
+
<%= activerecord_table_row(1) %>
|
75
|
+
<%= activerecord_table_row(2) %>
|
76
|
+
<%= activerecord_table_row(3) %>
|
77
|
+
When I go to the <%= plural %> page
|
78
|
+
And I click "Destroy" in the 2nd row
|
79
|
+
Then I should see the following <%= plural %>:
|
80
|
+
<%= html_table_header_row %>
|
81
|
+
<%= activerecord_table_row(1) %>
|
82
|
+
<%= activerecord_table_row(3) %>
|
83
|
+
And I should be on the <%= plural %> page
|
84
|
+
<% if successful_destroy_message %>
|
85
|
+
And I should see "<%= successful_destroy_message %>"
|
86
|
+
<% end -%>
|
87
|
+
|
88
|
+
<% if nifty? %>
|
89
|
+
<%= tags('@show @destroy @index') %>
|
90
|
+
Scenario: Delete a <%= singular %> via the show page
|
91
|
+
Given the following <%= plural %>:
|
92
|
+
<%= activerecord_table_header_row %>
|
93
|
+
<%= activerecord_table_row(1) %>
|
94
|
+
<%= activerecord_table_row(2) %>
|
95
|
+
<%= activerecord_table_row(3) %>
|
96
|
+
When I go to the page for the 2nd post
|
97
|
+
And I follow "Destroy"
|
98
|
+
Then I should see the following <%= plural %>:
|
99
|
+
<%= html_table_header_row %>
|
100
|
+
<%= activerecord_table_row(1) %>
|
101
|
+
<%= activerecord_table_row(3) %>
|
102
|
+
And I should be on the <%= plural %> page
|
103
|
+
And I should see "<%= successful_destroy_message %>"
|
104
|
+
<% end -%>
|
105
|
+
|
106
|
+
<%= tags('@new @create @show') %>
|
107
|
+
Scenario: Create a new <%= singular %>
|
108
|
+
Pending
|
109
|
+
# Given I am on the new <%= singular %> page
|
110
|
+
# When I fill in the following:
|
111
|
+
# <%= form_single_resource_commented %>
|
112
|
+
# And I press "<%= create_button_title %>"
|
113
|
+
# Then I should see "<%= successful_create_message %>"
|
114
|
+
# And I should see the following <%= singular %>:
|
115
|
+
# <%= html_single_resource_commented %>
|
116
|
+
#
|
117
|
+
# In order to confirm that the user is redirected to the correct page
|
118
|
+
# after create, you'll need to add an entry to paths.rb to uniquely
|
119
|
+
# find a <%= singular %>, e.g.:
|
120
|
+
#
|
121
|
+
# when /page for the <%= singular %> with name "([^"]*)"$/
|
122
|
+
# conditions = { :conditions => {:name => $1} }
|
123
|
+
# matches = <%= singular_title %>.all(conditions)
|
124
|
+
# if matches.size == 0
|
125
|
+
# raise "Could not find any <%= plural %> using criteria #{conditions.inspect}"
|
126
|
+
# elsif matches.size > 1
|
127
|
+
# raise "Could not find a unique <%= singular %> using criteria #{conditions.inspect} (#{matches.size} matches)"
|
128
|
+
# end
|
129
|
+
# <%= singular %>_path(matches.first)
|
130
|
+
#
|
131
|
+
# Then add a step such as this to the scenario:
|
132
|
+
#
|
133
|
+
# And I should be on the page for the <%= singular %> with name "..."
|
134
|
+
|
135
|
+
<%= tags('@new @create') %>
|
136
|
+
Scenario: Attempt to create a new <%= singular %> with invalid input
|
137
|
+
Pending
|
138
|
+
# <%= pending_explanation_1 %>
|
139
|
+
# Given I am on the new <%= singular %> page
|
140
|
+
# When I fill in the following:
|
141
|
+
# <%= form_single_resource_commented %>
|
142
|
+
# And I press "<%= create_button_title %>"
|
143
|
+
# Then I should see "<%= problems_intro %>"
|
144
|
+
#
|
145
|
+
# <%= pending_explanation_2 %>
|
146
|
+
#
|
147
|
+
# And I should be on the <%= plural %> page
|
148
|
+
# And I should see the following form field values:
|
149
|
+
# <%= html_single_resource_commented %>
|
150
|
+
|
151
|
+
<%= tags('@edit @update') %>
|
152
|
+
Scenario: Attempt to update a <%= singular %> with invalid input
|
153
|
+
Pending
|
154
|
+
# <%= pending_explanation_1 %>
|
155
|
+
# Given a <%= singular %> exists
|
156
|
+
# When I go to the edit page for that <%= singular %>
|
157
|
+
# And I fill in the following:
|
158
|
+
# <%= form_single_resource_commented %>
|
159
|
+
# And I press "<%= update_button_title %>"
|
160
|
+
# Then I should see "<%= problems_intro %>"
|
161
|
+
#
|
162
|
+
# <%= pending_explanation_2 %>
|
163
|
+
#
|
164
|
+
# And I should be on the page for that <%= singular %>
|
165
|
+
# And I should see the following form field values:
|
166
|
+
# <%= html_single_resource_commented %>
|
167
|
+
|
168
|
+
<%= tags('@edit @update @show') %>
|
169
|
+
Scenario: Update a <%= singular %>
|
170
|
+
Given a <%= singular %> exists
|
171
|
+
When I go to the edit page for that <%= singular %>
|
172
|
+
And I fill in the following:
|
173
|
+
<%= form_single_resource_updated %>
|
174
|
+
And I press "<%= update_button_title %>"
|
175
|
+
Then I should be on the page for that <%= singular %>
|
176
|
+
And I should see "<%= successful_update_message %>"
|
177
|
+
And I should see the following <%= singular %>:
|
178
|
+
<%= html_single_resource_updated %>
|
179
|
+
|
180
|
+
<%= tags('@index @new') %>
|
181
|
+
Scenario: Navigate from the <%= plural %> page to the new <%= singular %> page
|
182
|
+
Given I am on the <%= plural %> page
|
183
|
+
When I follow "New <%= singular_title %>"
|
184
|
+
Then I should be on the new <%= singular %> page
|
185
|
+
|
186
|
+
<%= tags('@index @show') %>
|
187
|
+
Scenario: Navigate from <%= plural %> page to the show <%= singular %> page
|
188
|
+
Given the following <%= plural %>:
|
189
|
+
<%= activerecord_table_header_row %>
|
190
|
+
<%= activerecord_table_row(1) %>
|
191
|
+
<%= activerecord_table_row(2) %>
|
192
|
+
<%= activerecord_table_row(3) %>
|
193
|
+
When I go to the <%= plural %> page
|
194
|
+
And I click "Show" in the 2nd row
|
195
|
+
Then I should be on the page for the 2nd <%= singular %>
|
196
|
+
|
197
|
+
<%= tags('@index @edit') %>
|
198
|
+
Scenario: Navigate from <%= plural %> page to the edit <%= singular %> page
|
199
|
+
Given the following <%= plural %>:
|
200
|
+
<%= activerecord_table_header_row %>
|
201
|
+
<%= activerecord_table_row(1) %>
|
202
|
+
<%= activerecord_table_row(2) %>
|
203
|
+
<%= activerecord_table_row(3) %>
|
204
|
+
When I go to the <%= plural %> page
|
205
|
+
And I click "Edit" in the 2nd row
|
206
|
+
Then I should be on the edit page for the 2nd <%= singular %>
|
207
|
+
|
208
|
+
<%= tags('@new @index') %>
|
209
|
+
Scenario: Navigate from new <%= singular %> page to <%= plural %> page
|
210
|
+
Given I am on the new <%= singular %> page
|
211
|
+
When I follow "<%= back_to_all %>"
|
212
|
+
Then I should be on the <%= plural %> page
|
213
|
+
|
214
|
+
<%= tags('@edit @show') %>
|
215
|
+
Scenario: Navigate from the edit <%= singular %> page to the show <%= singular %> page
|
216
|
+
Given a <%= singular %> exists
|
217
|
+
When I go to the edit page for that <%= singular %>
|
218
|
+
And I follow "Show"
|
219
|
+
Then I should be on the page for that <%= singular %>
|
220
|
+
|
221
|
+
<%= tags('@edit @index') %>
|
222
|
+
Scenario: Navigate from edit <%= singular %> page to the <%= plural %> page
|
223
|
+
Given a <%= singular %> exists
|
224
|
+
When I go to the edit page for that <%= singular %>
|
225
|
+
And I follow "<%= back_to_all %>"
|
226
|
+
Then I should be on the <%= plural %> page
|
227
|
+
|
228
|
+
<%= tags('@show @edit') %>
|
229
|
+
Scenario: Navigate from show <%= singular %> page to edit <%= singular %> page
|
230
|
+
Given a <%= singular %> exists
|
231
|
+
When I go to the page for that <%= singular %>
|
232
|
+
And I follow "Edit"
|
233
|
+
Then I should be on the edit page for that <%= singular %>
|
234
|
+
|
235
|
+
<%= tags('@show @index') %>
|
236
|
+
Scenario: Navigate from show <%= singular %> page to <%= plural %> page
|
237
|
+
Given a <%= singular %> exists
|
238
|
+
And I am on the page for that <%= singular %>
|
239
|
+
<% if nifty? %>
|
240
|
+
And I follow "View All"
|
241
|
+
<% else %>
|
242
|
+
And I follow "Back"
|
243
|
+
<% end %>
|
244
|
+
Then I should be on the <%= plural %> page
|
245
|
+
|
246
|
+
<%= tags('@index') %>
|
247
|
+
Scenario: <%= plural_title %> page title
|
248
|
+
When I go to the <%= plural %> page
|
249
|
+
Then the heading should be "<%= index_heading %>"
|
250
|
+
<% if index_title %>
|
251
|
+
And the title should be "<%= index_title %>"
|
252
|
+
<% end -%>
|
253
|
+
|
254
|
+
<%= tags('@show') %>
|
255
|
+
<% if show_heading || index_title %>
|
256
|
+
Scenario: <%= singular_title %> page title
|
257
|
+
Given a <%= singular %> exists
|
258
|
+
When I go to the page for that <%= singular %>
|
259
|
+
<% if show_heading %>
|
260
|
+
Then the heading should be "<%= show_heading %>"
|
261
|
+
<% end %>
|
262
|
+
<% if index_title %>
|
263
|
+
And the title should be "<%= show_title %>"
|
264
|
+
<% end -%>
|
265
|
+
<% end -%>
|
266
|
+
|
267
|
+
<%= tags('@new') %>
|
268
|
+
Scenario: New <%= singular %> page title
|
269
|
+
When I go to the new <%= singular %> page
|
270
|
+
Then the heading should be "<%= new_heading %>"
|
271
|
+
<% if index_title %>
|
272
|
+
And the title should be "<%= new_title %>"
|
273
|
+
<% end -%>
|
274
|
+
|
275
|
+
<%= tags('@edit') %>
|
276
|
+
Scenario: Edit <%= singular %> page title
|
277
|
+
Given a <%= singular %> exists
|
278
|
+
When I go to the edit page for that <%= singular %>
|
279
|
+
Then the heading should be "<%= edit_heading %>"
|
280
|
+
<% if index_title %>
|
281
|
+
And the title should be "<%= edit_title %>"
|
282
|
+
<% end -%>
|
@@ -0,0 +1,40 @@
|
|
1
|
+
<%= generated_by %>
|
2
|
+
|
3
|
+
Given /^a <%= singular %> exists$/ do
|
4
|
+
@<%= singular %> = <%= singular_title %>.create!(valid_<%= singular %>_attributes)
|
5
|
+
end
|
6
|
+
|
7
|
+
Then /^I should see the following <%= singular %>:$/ do |expected_table|
|
8
|
+
|
9
|
+
<% if nifty? %>
|
10
|
+
show_fields_css_query = 'body p strong'
|
11
|
+
<% else %>
|
12
|
+
show_fields_css_query = 'body p b'
|
13
|
+
<% end %>
|
14
|
+
|
15
|
+
actual_table = tableish(show_fields_css_query, lambda{|label| [label, label.next]})
|
16
|
+
actual = {}
|
17
|
+
actual_table.each do |form_entry|
|
18
|
+
attr_name = form_entry[0]
|
19
|
+
attr_value = form_entry[1]
|
20
|
+
actual[attr_name] = attr_value
|
21
|
+
end
|
22
|
+
assert_equal actual, expected_table.rows_hash
|
23
|
+
end
|
24
|
+
|
25
|
+
Then /^I should see the following <%= plural %>:$/ do |expected_table|
|
26
|
+
expected_table.diff!(tableish('table tr', 'td,th'))
|
27
|
+
end
|
28
|
+
|
29
|
+
Given /^the following <%= plural %>:$/ do |table|
|
30
|
+
@<%= plural %> = <%= singular_title %>.create!(table.hashes)
|
31
|
+
end
|
32
|
+
|
33
|
+
Given /^the following <%= singular %>:$/ do |table|
|
34
|
+
@<%= singular %> = <%= singular_title %>.create!(table.rows_hash)
|
35
|
+
end
|
36
|
+
|
37
|
+
def valid_<%= singular %>_attributes
|
38
|
+
# You may want to a factory for this
|
39
|
+
{}
|
40
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module CucumberScaffold
|
2
|
+
class InstallGenerator < Rails::Generators::Base
|
3
|
+
|
4
|
+
source_root File.expand_path('../templates', __FILE__)
|
5
|
+
|
6
|
+
def do_it
|
7
|
+
|
8
|
+
template('shared/web_steps_additional.rb', 'features/step_definitions/web_steps_additional.rb')
|
9
|
+
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
When /^I click "([^"]*)" in the (\d+)(?:st|nd|rd|th) row$/ do |link, pos|
|
2
|
+
within("table tr:nth-child(#{pos.to_i+1})") do
|
3
|
+
click_link link
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
7
|
+
Then /^the heading should be "([^"]*)"$/ do |heading|
|
8
|
+
Then %{I should see "#{heading}" within "h1"}
|
9
|
+
end
|
10
|
+
|
11
|
+
Then /^the title should be "([^"]*)"$/ do |title|
|
12
|
+
Then %{I should see "#{title}" within "title"}
|
13
|
+
end
|
14
|
+
|
15
|
+
When /^I should see the following form field values:$/ do |table|
|
16
|
+
form_fields = tableish('form label', lambda{ |label| [label, form_field_for_label(label)]})
|
17
|
+
form_fields_hash = {}
|
18
|
+
form_fields.each do |form_field|
|
19
|
+
attr_name = form_field[0]
|
20
|
+
attr_value = form_field[1]
|
21
|
+
form_fields_hash[attr_name] = attr_value
|
22
|
+
end
|
23
|
+
assert_equal table.rows_hash, form_fields_hash
|
24
|
+
end
|
25
|
+
|
26
|
+
def form_field_for_label(label)
|
27
|
+
input_tags = label.parent.css('input,textarea')
|
28
|
+
return if input_tags.size == 0
|
29
|
+
if input_tags.size > 1
|
30
|
+
raise "Wrong number of input tags while parsing form (found #{input_tags.size})"
|
31
|
+
end
|
32
|
+
input_tag = input_tags.first
|
33
|
+
if input_tag.name == 'textarea'
|
34
|
+
input_tag.inner_html
|
35
|
+
elsif input_tag.name == 'input'
|
36
|
+
input_tag['value']
|
37
|
+
end
|
38
|
+
end
|
metadata
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cucumber_scaffold
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 0.1.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Andy Waite
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-11-06 00:00:00 +00:00
|
19
|
+
default_executable:
|
20
|
+
dependencies: []
|
21
|
+
|
22
|
+
description: Generate scaffolding for Cucumber features and steps definitions
|
23
|
+
email: andy@andywaite.com
|
24
|
+
executables: []
|
25
|
+
|
26
|
+
extensions: []
|
27
|
+
|
28
|
+
extra_rdoc_files:
|
29
|
+
- README.rdoc
|
30
|
+
- TODO
|
31
|
+
- lib/generators/cucumber_scaffold/feature/USAGE
|
32
|
+
- lib/generators/cucumber_scaffold/feature/feature_generator.rb
|
33
|
+
- lib/generators/cucumber_scaffold/feature/templates/feature.feature
|
34
|
+
- lib/generators/cucumber_scaffold/feature/templates/steps.rb
|
35
|
+
- lib/generators/cucumber_scaffold/install/USAGE
|
36
|
+
- lib/generators/cucumber_scaffold/install/install_generator.rb
|
37
|
+
- lib/generators/cucumber_scaffold/install/templates/shared/web_steps_additional.rb
|
38
|
+
files:
|
39
|
+
- Manifest
|
40
|
+
- README.rdoc
|
41
|
+
- Rakefile
|
42
|
+
- TODO
|
43
|
+
- cucumber_scaffold.gemspec
|
44
|
+
- lib/generators/cucumber_scaffold/feature/USAGE
|
45
|
+
- lib/generators/cucumber_scaffold/feature/feature_generator.rb
|
46
|
+
- lib/generators/cucumber_scaffold/feature/templates/feature.feature
|
47
|
+
- lib/generators/cucumber_scaffold/feature/templates/steps.rb
|
48
|
+
- lib/generators/cucumber_scaffold/install/USAGE
|
49
|
+
- lib/generators/cucumber_scaffold/install/install_generator.rb
|
50
|
+
- lib/generators/cucumber_scaffold/install/templates/shared/web_steps_additional.rb
|
51
|
+
has_rdoc: true
|
52
|
+
homepage: http://github.com/andyw8/cucumber_scaffold
|
53
|
+
licenses: []
|
54
|
+
|
55
|
+
post_install_message:
|
56
|
+
rdoc_options:
|
57
|
+
- --line-numbers
|
58
|
+
- --inline-source
|
59
|
+
- --title
|
60
|
+
- Cucumber_scaffold
|
61
|
+
- --main
|
62
|
+
- README.rdoc
|
63
|
+
require_paths:
|
64
|
+
- lib
|
65
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
hash: 3
|
71
|
+
segments:
|
72
|
+
- 0
|
73
|
+
version: "0"
|
74
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
75
|
+
none: false
|
76
|
+
requirements:
|
77
|
+
- - ">="
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
hash: 11
|
80
|
+
segments:
|
81
|
+
- 1
|
82
|
+
- 2
|
83
|
+
version: "1.2"
|
84
|
+
requirements: []
|
85
|
+
|
86
|
+
rubyforge_project: cucumber_scaffold
|
87
|
+
rubygems_version: 1.3.7
|
88
|
+
signing_key:
|
89
|
+
specification_version: 3
|
90
|
+
summary: Generate scaffolding for Cucumber features and steps definitions
|
91
|
+
test_files: []
|
92
|
+
|