cucumber_scaffold 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/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
|
+
|