mrflip-pickle 0.1.13
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +147 -0
- data/License.txt +20 -0
- data/README.rdoc +202 -0
- data/Todo.txt +4 -0
- data/lib/pickle.rb +26 -0
- data/lib/pickle/adapter.rb +87 -0
- data/lib/pickle/config.rb +48 -0
- data/lib/pickle/email.rb +36 -0
- data/lib/pickle/email/parser.rb +18 -0
- data/lib/pickle/email/world.rb +13 -0
- data/lib/pickle/parser.rb +65 -0
- data/lib/pickle/parser/matchers.rb +87 -0
- data/lib/pickle/path.rb +44 -0
- data/lib/pickle/path/world.rb +5 -0
- data/lib/pickle/session.rb +151 -0
- data/lib/pickle/session/parser.rb +24 -0
- data/lib/pickle/version.rb +9 -0
- data/lib/pickle/world.rb +9 -0
- data/rails_generators/pickle/pickle_generator.rb +41 -0
- data/rails_generators/pickle/templates/email_steps.rb +50 -0
- data/rails_generators/pickle/templates/env.rb +14 -0
- data/rails_generators/pickle/templates/paths.rb +20 -0
- data/rails_generators/pickle/templates/pickle_steps.rb +41 -0
- data/spec/lib/pickle_adapter_spec.rb +164 -0
- data/spec/lib/pickle_config_spec.rb +97 -0
- data/spec/lib/pickle_email_parser_spec.rb +49 -0
- data/spec/lib/pickle_email_spec.rb +131 -0
- data/spec/lib/pickle_parser_matchers_spec.rb +70 -0
- data/spec/lib/pickle_parser_spec.rb +154 -0
- data/spec/lib/pickle_path_spec.rb +77 -0
- data/spec/lib/pickle_session_spec.rb +337 -0
- data/spec/lib/pickle_spec.rb +24 -0
- metadata +94 -0
data/History.txt
ADDED
@@ -0,0 +1,147 @@
|
|
1
|
+
== 0.1.13 - 16 June 2009
|
2
|
+
|
3
|
+
* 2 minor enhancements
|
4
|
+
* model! and created_model! raise an error if pickle name can't be found
|
5
|
+
* path_to_pickle uses the above to give back a better error message
|
6
|
+
|
7
|
+
|
8
|
+
== 0.1.12 - 7 Apr 2009
|
9
|
+
|
10
|
+
* 2 minor enhancements
|
11
|
+
* rationalised Rakefile
|
12
|
+
* update World extensions for latest cucumber changes
|
13
|
+
|
14
|
+
|
15
|
+
== 0.1.11 - 22 Feb 2009
|
16
|
+
|
17
|
+
* 2 minor enhancements
|
18
|
+
* Pickle now supports multiple machinist blueprints
|
19
|
+
* Fix confusing adapter/adaptor comment generator comment
|
20
|
+
|
21
|
+
|
22
|
+
== 0.1.10 - 13 Feb 2009
|
23
|
+
|
24
|
+
* 2 minor enhancements
|
25
|
+
* Made pickle paths generator compatible with latest cucumber
|
26
|
+
* Simplified and Rakefile, including auto push api docs to gh-pages on ci build
|
27
|
+
|
28
|
+
|
29
|
+
== 0.1.9 - 29 Jan 2009
|
30
|
+
|
31
|
+
* 1 minor enhancement
|
32
|
+
* Pickle::Adapter.model_classes excludes those without tables
|
33
|
+
|
34
|
+
|
35
|
+
== 0.1.8 - 29 Jan 2009
|
36
|
+
|
37
|
+
* API change
|
38
|
+
* pickle_path becomes path_to_pickle, to avoid named route clashes
|
39
|
+
|
40
|
+
* 2 minor enhancements
|
41
|
+
* Updated features for cucumber 0.2 compat
|
42
|
+
* Made paths allow for optional possesives
|
43
|
+
|
44
|
+
|
45
|
+
== 0,1,7
|
46
|
+
|
47
|
+
* 2 API changes
|
48
|
+
* script/generate pickle path[s] now amends the features/support/paths.rb file
|
49
|
+
instead of creating pge_to_path and path_steps.
|
50
|
+
|
51
|
+
* pickle_email_steps is renamed email_steps
|
52
|
+
|
53
|
+
|
54
|
+
== 0.1.6
|
55
|
+
|
56
|
+
* 1 API change
|
57
|
+
* to use pickle env.rb should contain "require 'pickle/world'". You should remove all trace of
|
58
|
+
pickle from features/support/env.rb and re run script/generate pickle
|
59
|
+
|
60
|
+
* 2 major enhancements
|
61
|
+
|
62
|
+
* generate email steps with `script/generate pickle email`
|
63
|
+
email steps allow you to do things like this:
|
64
|
+
|
65
|
+
Then 2 emails should be delivered
|
66
|
+
And the first email should be delivered to fred@gmail.com
|
67
|
+
And the 2nd email should be delivered to the user: "ethel"
|
68
|
+
|
69
|
+
Then 1 email should be delivered with subject: "Activate your account"
|
70
|
+
And the email should link to the user's page
|
71
|
+
|
72
|
+
take a look at features/step_definitions/pickle_email_steps.rb
|
73
|
+
|
74
|
+
* generate path steps with `script/generate pickle path`
|
75
|
+
path steps allow you to do things like this
|
76
|
+
|
77
|
+
When I go to the comment's page
|
78
|
+
Then I should be at the user's new comment page
|
79
|
+
|
80
|
+
take a look at features/step_definitions/pickle_path_steps.rb, and modify page_to_path to suit your needs
|
81
|
+
|
82
|
+
* 4 minor enhancements
|
83
|
+
* Improved documentation
|
84
|
+
* abstract models no longer kill pickle
|
85
|
+
* Actually test that the generators work
|
86
|
+
* Made Pickle::Session a plain ole mixin, as a separate class was unnecessary
|
87
|
+
* Pickle uses the cucumber World API
|
88
|
+
|
89
|
+
|
90
|
+
== 0.1.5
|
91
|
+
|
92
|
+
* API change
|
93
|
+
* CaptureModel, etc are now 'capture_model' methods
|
94
|
+
|
95
|
+
* 3 major enhancements
|
96
|
+
* Steps for asserting that <n> models exist, matching certain criteria
|
97
|
+
* Steps for asserting associations added to generated pickle steps
|
98
|
+
'Then the user should be in the post's commenters'
|
99
|
+
'Then the forum: "awesome" should be the 2nd post's forum'
|
100
|
+
* configuration can now occur any time before a step is defined, which makes
|
101
|
+
for much more intuitive env.rb
|
102
|
+
|
103
|
+
* 2 minor enhancement
|
104
|
+
* predicate matching is less prone to step conflicts because we preload a
|
105
|
+
big list of all the predicate and column methods
|
106
|
+
* field values now handle booleans and numerics
|
107
|
+
|
108
|
+
|
109
|
+
== 0.1.4
|
110
|
+
|
111
|
+
* 1 major enhancement
|
112
|
+
* You can create multiple models with ease, for eg.
|
113
|
+
'Given 10 users exist with role: "admin"'
|
114
|
+
|
115
|
+
* 1 minor enhancement
|
116
|
+
* You can do Pickle.configure (just like Webrat.configure)
|
117
|
+
|
118
|
+
|
119
|
+
== 0.1.3 - Bugfix release
|
120
|
+
|
121
|
+
* 1 minor enhancement
|
122
|
+
* make generated steps compatible with Rails 2.1
|
123
|
+
|
124
|
+
|
125
|
+
== 0.1.2
|
126
|
+
|
127
|
+
* 2 major enhancements
|
128
|
+
* create your pickle steps with script/generate pickle
|
129
|
+
* Adapter based architecture, supports Machinist, FactoryGirl, and vanilla ActiveRecord
|
130
|
+
|
131
|
+
* 1 minor enhancement
|
132
|
+
* model_names now defaults to subclasses of AR::Base
|
133
|
+
* #original_model => #created_model
|
134
|
+
|
135
|
+
|
136
|
+
== 0.1.1
|
137
|
+
|
138
|
+
* 1 major enhancement:
|
139
|
+
* made pickle a github gem
|
140
|
+
|
141
|
+
* 1 minor enhancement:
|
142
|
+
* Added intentions for pickle in README.textile
|
143
|
+
|
144
|
+
|
145
|
+
== Prior to gems
|
146
|
+
|
147
|
+
* Initial release: everything is subject to sweeping change
|
data/License.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2008-2009 Ian White - ian.w.white@gmail.com
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,202 @@
|
|
1
|
+
= pickle
|
2
|
+
|
3
|
+
Pickle gives you cucumber steps that create your models easily from factory-girl or
|
4
|
+
machinist factories/blueprints. You can also just use ActiveRecord but it's not as cool.
|
5
|
+
|
6
|
+
References to the models are stored, not necessarily for the purpose of checking the db
|
7
|
+
(although you could use it for that), but for enabling easy reference to urls, and for
|
8
|
+
building complex givens which require a bunch of models collaborating
|
9
|
+
|
10
|
+
== CI
|
11
|
+
|
12
|
+
It's tested against all stable branches of 2.x rails, and edge, with the latest versions of rspec, cucumber, factory_girl, machinist.
|
13
|
+
|
14
|
+
== Install
|
15
|
+
|
16
|
+
Install pickle either as a rails plugin, or a gem
|
17
|
+
|
18
|
+
# plugin
|
19
|
+
script/plugin install git://github.com/ianwhite/pickle.git
|
20
|
+
|
21
|
+
# or, plugin as submodule
|
22
|
+
git submodule add git://github.com/ianwhite/pickle.git vendor/plugins/pickle
|
23
|
+
|
24
|
+
# or, gem
|
25
|
+
sudo gem install ianwhite-pickle
|
26
|
+
|
27
|
+
== Get Started
|
28
|
+
|
29
|
+
(you'd better install cucumber)
|
30
|
+
|
31
|
+
script/generate pickle [paths] [email]
|
32
|
+
|
33
|
+
Now have a look at <tt>features/step_definitions/pickle_steps.rb</tt>
|
34
|
+
|
35
|
+
If you want path steps and email steps then just add 'paths' and/or 'email'. The code/steps will be
|
36
|
+
written to <tt>features/env/paths.rb</tt> and
|
37
|
+
<tt>features/step_definitions/email_steps.rb</tt> respectively.
|
38
|
+
|
39
|
+
=== Using with plain ole Active Record
|
40
|
+
|
41
|
+
If you have an AR called 'Post', with required fields 'title', and 'body', then you can now write
|
42
|
+
steps like this
|
43
|
+
|
44
|
+
Given a post exists with title: "My Post", body: "My body"
|
45
|
+
|
46
|
+
=== Using with factory-girl or machinist
|
47
|
+
|
48
|
+
But you're using Machinist or FactoryGirl right?! To leverage all of the factories/blueprints
|
49
|
+
you've written, you can just do stuff like
|
50
|
+
|
51
|
+
Given a user exists
|
52
|
+
And another user exists with role: "admin"
|
53
|
+
|
54
|
+
# later
|
55
|
+
Then a user should exist with name: "Fred"
|
56
|
+
And that user should be activated # this uses rspec predicate matchers
|
57
|
+
|
58
|
+
==== Machinst: require your blueprints and reset Shams
|
59
|
+
|
60
|
+
(The latest version of pickle supports {multiple blueprints}[http://github.com/notahat/machinist/commit/d6492e6927a8aa1819926e48b22377171fd20496], for
|
61
|
+
earlier versions of machinist use pickle <= 0.1.10)
|
62
|
+
|
63
|
+
In your <tt>features/support/env.rb</tt> add the following lines at the bottom
|
64
|
+
|
65
|
+
require "#{Rails.root}/spec/blueprints" # or wherever they live
|
66
|
+
Before { Sham.reset } # reset Shams in between scenarios
|
67
|
+
|
68
|
+
=== Configuring Pickle
|
69
|
+
|
70
|
+
You can tell pickle to use another factory adapter (see Pickle::Adapter), or
|
71
|
+
create mappings from english expressions to pickle model names. You can also
|
72
|
+
override many of the options on the Pickle::Config object if you so choose
|
73
|
+
|
74
|
+
require 'pickle/world'
|
75
|
+
|
76
|
+
Pickle.configure do |config|
|
77
|
+
config.adapters = [:machinist, YourOwnAdapterClass]
|
78
|
+
config.map 'me', 'myself', 'my', 'I', :to => 'user: "me"'
|
79
|
+
end
|
80
|
+
|
81
|
+
== API
|
82
|
+
|
83
|
+
=== Steps
|
84
|
+
|
85
|
+
When you run <tt>script/generate pickle</tt> you get the following steps
|
86
|
+
|
87
|
+
==== Given steps
|
88
|
+
|
89
|
+
"Given <b>a model</b> exists", e.g.
|
90
|
+
|
91
|
+
Given a user exists
|
92
|
+
Given a user: "fred" exists
|
93
|
+
Given the user exists
|
94
|
+
|
95
|
+
"Given <b>a model</b> exists with <b>fields</b>", e.g.
|
96
|
+
|
97
|
+
Given a user exists with name: "Fred"
|
98
|
+
Given a user exists with name: "Fred", activated: false
|
99
|
+
|
100
|
+
You can refer to other models in the fields
|
101
|
+
|
102
|
+
Given a user exists
|
103
|
+
And a post exists with author: the user
|
104
|
+
|
105
|
+
Given a person: "fred" exists
|
106
|
+
And a person: "ethel" exists
|
107
|
+
And a fatherhood exists with parent: user "fred", child: user "ethel"
|
108
|
+
|
109
|
+
"Given <b>n</b> models exist", e.g.
|
110
|
+
|
111
|
+
Given 10 users exist
|
112
|
+
|
113
|
+
"Given <b>n</b> <b>models</b> exist with <b>fields</b>", examples:
|
114
|
+
|
115
|
+
Given 10 users exist with activated: false
|
116
|
+
|
117
|
+
==== Then steps
|
118
|
+
|
119
|
+
===== Asserting existence of models
|
120
|
+
|
121
|
+
"Then <b>a model</b> should exist", e.g.
|
122
|
+
|
123
|
+
Then a user should exist
|
124
|
+
|
125
|
+
"Then <b>a model</b> should exist with <b>fields</b>", e.g.
|
126
|
+
|
127
|
+
Then a user: "fred" should exist with name: "Fred" # we can label the found user for later use
|
128
|
+
|
129
|
+
You can use other models, booleans, numerics, and strings as fields
|
130
|
+
|
131
|
+
Then a person should exist with child: person "ethel"
|
132
|
+
Then a user should exist with activated: false
|
133
|
+
Then a user should exist with activated: true, email: "fred@gmail.com"
|
134
|
+
|
135
|
+
"Then <b>n</b> <b>models</b> should exist", e.g.
|
136
|
+
|
137
|
+
Then 10 events should exist
|
138
|
+
|
139
|
+
"Then <b>n</b> <b>models</b> should exist with <b>fields</b>", e.g.
|
140
|
+
|
141
|
+
Then 2 people should exist with father: person "fred"
|
142
|
+
|
143
|
+
===== Asserting associations
|
144
|
+
|
145
|
+
One-to-one assocs: "Then <b>a model</b> should be <b>other model</b>'s <b>association</b>", e.g.
|
146
|
+
|
147
|
+
Then the person: "fred" should be person: "ethel"'s father
|
148
|
+
|
149
|
+
Many-to-one assocs: "Then <b>a model</b> should be [in|one of] <b>other model</b>'s <b>association</b>", e.g.
|
150
|
+
|
151
|
+
Then the person: "ethel" should be one of person: "fred"'s children
|
152
|
+
Then the comment should be in the post's comments
|
153
|
+
|
154
|
+
===== Asserting predicate methods
|
155
|
+
|
156
|
+
"Then <b>a model</b> should [be|have] [a|an] <b>predicate</b>", e.g.
|
157
|
+
|
158
|
+
Then the user should have a status # => user.status?.should == true
|
159
|
+
Then the car: "batmobile" should be fast # => car.fast?.should == true
|
160
|
+
|
161
|
+
"Then <b>a model</b> should [be|have] [a|an] <b>predicate</b>", e.g.
|
162
|
+
|
163
|
+
Then person: "fred" should not be childless # => fred.childless?.should == false
|
164
|
+
|
165
|
+
=== Regexps for use in your own steps
|
166
|
+
|
167
|
+
By default you get some regexps available in the main namespace for use
|
168
|
+
in creating your own steps: `capture_model`, `capture_fields`, and others (see lib/pickle.rb)
|
169
|
+
|
170
|
+
(You can use any of the regexps that Pickle uses by using the Pickle.parser namespace, see
|
171
|
+
Pickle::Parser::Matchers for the methods available)
|
172
|
+
|
173
|
+
*capture_model*
|
174
|
+
|
175
|
+
Given /^#{capture_model} exists$/ do |model_name|
|
176
|
+
model(model_name).should_not == nil
|
177
|
+
end
|
178
|
+
|
179
|
+
Then /^I should be at the (.*?) page$/ |page|
|
180
|
+
if page =~ /#{capture_model}'s/
|
181
|
+
url_for(model($1))
|
182
|
+
else
|
183
|
+
# ...
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
Then /^#{capture_model} should be one of #{capture_model}'s posts$/ do |post, forum|
|
188
|
+
model(forum).posts.should include(post)
|
189
|
+
end
|
190
|
+
|
191
|
+
*capture_fields*
|
192
|
+
|
193
|
+
This is useful for setting attributes, and knows about pickle model names so that you
|
194
|
+
can build up composite objects with ease
|
195
|
+
|
196
|
+
Given /^#{capture_model} exists with #{capture_fields}$/ do |model_name, fields|
|
197
|
+
create_model(model_name, fields)
|
198
|
+
end
|
199
|
+
|
200
|
+
# example of use
|
201
|
+
Given a user exists
|
202
|
+
And a post exists with author: the user # this step will assign the above user as :author on the post
|
data/Todo.txt
ADDED
data/lib/pickle.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
require 'pickle/version'
|
3
|
+
require 'pickle/adapter'
|
4
|
+
require 'pickle/config'
|
5
|
+
require 'pickle/parser'
|
6
|
+
require 'pickle/session'
|
7
|
+
require 'pickle/session/parser'
|
8
|
+
|
9
|
+
# make the parser aware of models in the session (for fields refering to models)
|
10
|
+
Pickle::Parser.send :include, Pickle::Session::Parser
|
11
|
+
|
12
|
+
module Pickle
|
13
|
+
class << self
|
14
|
+
def config
|
15
|
+
@config ||= Config.new
|
16
|
+
end
|
17
|
+
|
18
|
+
def configure(&block)
|
19
|
+
config.configure(&block)
|
20
|
+
end
|
21
|
+
|
22
|
+
def parser(options = {})
|
23
|
+
@parser ||= Parser.new({:config => config}.merge(options))
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module Pickle
|
2
|
+
# Abstract Factory adapter class, if you have a factory type setup, you
|
3
|
+
# can easily create an adaptor to make it work with Pickle.
|
4
|
+
#
|
5
|
+
# The factory adaptor must have a #factories class method that returns
|
6
|
+
# its instances, and each instance must respond to:
|
7
|
+
#
|
8
|
+
# #name : identifies the factory by name (default is attr_reader)
|
9
|
+
# #klass : returns the associated model class for this factory (default is attr_reader)
|
10
|
+
# #create(attrs = {}) : returns a newly created object
|
11
|
+
class Adapter
|
12
|
+
attr_reader :name, :klass
|
13
|
+
|
14
|
+
def self.factories
|
15
|
+
raise NotImplementedError, "return an array of factory adapter objects"
|
16
|
+
end
|
17
|
+
|
18
|
+
def create(attrs = {})
|
19
|
+
raise NotImplementedError, "create and return an object with the given attributes"
|
20
|
+
end
|
21
|
+
|
22
|
+
cattr_writer :model_classes
|
23
|
+
self.model_classes = nil
|
24
|
+
|
25
|
+
def self.model_classes
|
26
|
+
# remove abstract, framework, and non-table classes
|
27
|
+
@@model_classes ||= ::ActiveRecord::Base.send(:subclasses).reject do |klass|
|
28
|
+
klass.abstract_class? || !klass.table_exists? ||
|
29
|
+
(defined?(CGI::Session::ActiveRecordStore::Session) && klass == CGI::Session::ActiveRecordStore::Session) ||
|
30
|
+
(defined?(::ActiveRecord::SessionStore::Session) && klass == ::ActiveRecord::SessionStore::Session)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# machinist adapter
|
35
|
+
class Machinist < Adapter
|
36
|
+
def self.factories
|
37
|
+
factories = []
|
38
|
+
model_classes.each do |klass|
|
39
|
+
if blueprints = klass.instance_variable_get('@blueprints')
|
40
|
+
blueprints.keys.each {|blueprint| factories << new(klass, blueprint)}
|
41
|
+
end
|
42
|
+
end
|
43
|
+
factories
|
44
|
+
end
|
45
|
+
|
46
|
+
def initialize(klass, blueprint)
|
47
|
+
@klass, @blueprint = klass, blueprint
|
48
|
+
@name = @klass.name.underscore.gsub('/','_')
|
49
|
+
@name = "#{@blueprint}_#{@name}" unless @blueprint == :master
|
50
|
+
end
|
51
|
+
|
52
|
+
def create(attrs = {})
|
53
|
+
@klass.send(:make, @blueprint, attrs)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# factory-girl adapter
|
58
|
+
class FactoryGirl < Adapter
|
59
|
+
def self.factories
|
60
|
+
(::Factory.factories.values rescue []).map {|factory| new(factory)}
|
61
|
+
end
|
62
|
+
|
63
|
+
def initialize(factory)
|
64
|
+
@klass, @name = factory.build_class, factory.factory_name.to_s
|
65
|
+
end
|
66
|
+
|
67
|
+
def create(attrs = {})
|
68
|
+
Factory.create(@name, attrs)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# fallback active record adapter
|
73
|
+
class ActiveRecord < Adapter
|
74
|
+
def self.factories
|
75
|
+
model_classes.map {|klass| new(klass) }
|
76
|
+
end
|
77
|
+
|
78
|
+
def initialize(klass)
|
79
|
+
@klass, @name = klass, klass.name.underscore.gsub('/','_')
|
80
|
+
end
|
81
|
+
|
82
|
+
def create(attrs = {})
|
83
|
+
@klass.send(:create!, attrs)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|