pickle 0.5.0 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8730ddaad2e1e21064b59b145a05766f77be5d9c
4
- data.tar.gz: 74edf4182c09e69e45bc478d0d370a6210f9aa96
3
+ metadata.gz: 539f558a14741424c0a8da2e4a9aee5c0eae8acf
4
+ data.tar.gz: b57e316aa5dbc009cb4ed513ffe0bdfa294cb0a4
5
5
  SHA512:
6
- metadata.gz: 1c19f299257c90276c96c52e36b954af848432669c47fe60e297a40e3bdcc105662fa7219c384c932c8c8fb7b92378f6d98413cf3655e001ed7f1fc5d25eaac7
7
- data.tar.gz: be13a9cb03e8f3f42f6e043c26fb43bacdfa20e6c6fa7cf06fcec0933488aa3fcfd503da10ea995940f9b790ad3ae6d35e96ecda66f3d25da00eb6c11717bd0b
6
+ metadata.gz: 8f9bb9f3e62e16bd4d55c63a9fa41752cc341b522a7b3805fb9ede47b2fafb7c10ba6171c8c691ef530c615bfa4a9d6f91e1ee6c879d0e374fdf5ef21c0d1ad1
7
+ data.tar.gz: ee37511e749bd0eb4f42e8801e7188051f36ea990207efdb7924dacb14973162a78188afd1d0da68e2b21aade94ae1e0c0b67d65aa3a39b36ce698bda1b4c31b
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- pickle (0.4.11)
4
+ pickle (0.5.1)
5
5
  cucumber (>= 0.8)
6
6
  rake
7
7
 
@@ -38,47 +38,47 @@ GEM
38
38
  multi_json (~> 1.0)
39
39
  arel (2.2.3)
40
40
  builder (3.0.4)
41
- capybara (2.4.1)
41
+ capybara (2.4.4)
42
42
  mime-types (>= 1.16)
43
43
  nokogiri (>= 1.3.3)
44
44
  rack (>= 1.0.0)
45
45
  rack-test (>= 0.5.4)
46
46
  xpath (~> 2.0)
47
- cucumber (1.3.16)
47
+ cucumber (1.3.18)
48
48
  builder (>= 2.1.2)
49
49
  diff-lcs (>= 1.1.3)
50
50
  gherkin (~> 2.12)
51
51
  multi_json (>= 1.7.5, < 2.0)
52
52
  multi_test (>= 0.1.1)
53
- cucumber-rails (1.4.1)
53
+ cucumber-rails (1.4.2)
54
54
  capybara (>= 1.1.2, < 3)
55
55
  cucumber (>= 1.3.8, < 2)
56
- mime-types (~> 1.16)
56
+ mime-types (>= 1.16, < 3)
57
57
  nokogiri (~> 1.5)
58
58
  rails (>= 3, < 5)
59
- database_cleaner (1.3.0)
59
+ database_cleaner (1.4.0)
60
60
  diff-lcs (1.2.5)
61
61
  erubis (2.7.0)
62
- fabrication (2.11.3)
63
- factory_girl (4.4.0)
62
+ fabrication (2.12.0)
63
+ factory_girl (4.5.0)
64
64
  activesupport (>= 3.0.0)
65
65
  gherkin (2.12.2)
66
66
  multi_json (~> 1.3)
67
- git (1.2.8)
67
+ git (1.2.9)
68
68
  hike (1.2.3)
69
- i18n (0.6.11)
70
- json (1.8.1)
69
+ i18n (0.7.0)
70
+ json (1.8.2)
71
71
  machinist (2.0)
72
72
  mail (2.4.4)
73
73
  i18n (>= 0.4.0)
74
74
  mime-types (~> 1.16)
75
75
  treetop (~> 1.4.8)
76
76
  mime-types (1.25.1)
77
- mini_portile (0.6.0)
77
+ mini_portile (0.6.2)
78
78
  multi_json (1.10.1)
79
79
  multi_test (0.1.1)
80
- nokogiri (1.6.3.1)
81
- mini_portile (= 0.6.0)
80
+ nokogiri (1.6.5)
81
+ mini_portile (~> 0.6.0)
82
82
  polyglot (0.3.5)
83
83
  rack (1.3.10)
84
84
  rack-cache (1.2)
@@ -87,7 +87,7 @@ GEM
87
87
  rack (>= 1.0.0)
88
88
  rack-ssl (1.3.4)
89
89
  rack
90
- rack-test (0.6.2)
90
+ rack-test (0.6.3)
91
91
  rack (>= 1.0)
92
92
  rails (3.1.12)
93
93
  actionmailer (= 3.1.12)
@@ -104,41 +104,39 @@ GEM
104
104
  rake (>= 0.8.7)
105
105
  rdoc (~> 3.4)
106
106
  thor (~> 0.14.6)
107
- rake (10.3.2)
107
+ rake (10.4.2)
108
108
  rdoc (3.12.2)
109
109
  json (~> 1.4)
110
- rspec-core (3.0.3)
111
- rspec-support (~> 3.0.0)
112
- rspec-expectations (3.0.3)
110
+ rspec-core (3.1.7)
111
+ rspec-support (~> 3.1.0)
112
+ rspec-expectations (3.1.2)
113
113
  diff-lcs (>= 1.2.0, < 2.0)
114
- rspec-support (~> 3.0.0)
115
- rspec-mocks (3.0.3)
116
- rspec-support (~> 3.0.0)
117
- rspec-rails (3.0.2)
114
+ rspec-support (~> 3.1.0)
115
+ rspec-mocks (3.1.3)
116
+ rspec-support (~> 3.1.0)
117
+ rspec-rails (3.1.0)
118
118
  actionpack (>= 3.0)
119
119
  activesupport (>= 3.0)
120
120
  railties (>= 3.0)
121
- rspec-core (~> 3.0.0)
122
- rspec-expectations (~> 3.0.0)
123
- rspec-mocks (~> 3.0.0)
124
- rspec-support (~> 3.0.0)
125
- rspec-support (3.0.3)
126
- sprockets (2.0.4)
121
+ rspec-core (~> 3.1.0)
122
+ rspec-expectations (~> 3.1.0)
123
+ rspec-mocks (~> 3.1.0)
124
+ rspec-support (~> 3.1.0)
125
+ rspec-support (3.1.2)
126
+ sprockets (2.0.5)
127
127
  hike (~> 1.2)
128
128
  rack (~> 1.0)
129
129
  tilt (~> 1.1, != 1.3.0)
130
- sqlite3 (1.3.9)
131
- sqlite3-ruby (1.3.3)
132
- sqlite3 (>= 1.3.3)
130
+ sqlite3 (1.3.10)
133
131
  thor (0.14.6)
134
132
  tilt (1.4.1)
135
133
  treetop (1.4.15)
136
134
  polyglot
137
135
  polyglot (>= 0.3.1)
138
- tzinfo (0.3.41)
136
+ tzinfo (0.3.42)
139
137
  xpath (2.0.0)
140
138
  nokogiri (~> 1.3)
141
- yard (0.8.7.4)
139
+ yard (0.8.7.6)
142
140
 
143
141
  PLATFORMS
144
142
  ruby
@@ -156,5 +154,5 @@ DEPENDENCIES
156
154
  rack
157
155
  rails (~> 3.1.0)
158
156
  rspec-rails (~> 3.0)
159
- sqlite3-ruby
157
+ sqlite3
160
158
  yard
@@ -1,3 +1,18 @@
1
+ == 0.5.1
2
+
3
+ * Add support to use Factory.build [Erik Peterson]
4
+ * Support factory_girl2 aliases [Jon Kinney]
5
+ * Better email validation messages [Kevin Ross]
6
+ * Prefer the html_part in a multipart email [Jason Lee, Jon Kinney]
7
+ * Fix email open_in_browser function [Daniel Zollinger]
8
+ * Support Mongoid associations in find_model/s [Ches Martin]
9
+ * Fix Mongoid for anonymous classes [Matt Royal]
10
+ * Fix Mongoid finders for later versions [James Le Cuirot, Jules Copeland]
11
+ * Fix ActiveRecord finders for later versions [Blake Thomas]
12
+ * Support "should not exist" for models from a table [Pierre-Yves Chauveau]
13
+ * Reduce number of queries when creating multiple models [James Le Cuirot]
14
+ * Various test improvements [James Le Cuirot]
15
+
1
16
  == 0.5.0
2
17
 
3
18
  * Drop support for Machinist 1 [James Le Cuirot]
@@ -0,0 +1,566 @@
1
+ # pickle
2
+
3
+ [<img src="https://travis-ci.org/ianwhite/pickle.svg" alt="Build Status"/>](https://travis-ci.org/ianwhite/pickle)
4
+
5
+ Pickle gives you cucumber steps that create your models easily from factory-girl, machinist, or fabrication. You can also just use ActiveRecord as a factory but it's not as cool. Pickle can make use of different ORMs for finding records. Currently ActiveRecord, DataMapper, MongoID adapters are provided. More adapters welcome!
6
+
7
+ References to the models are stored in the current world, not necessarily for the purpose of checking the db (although you could use it for that), but for enabling easy reference to urls, and for building complex givens which require a bunch of models collaborating
8
+
9
+ ## Quickstart
10
+
11
+ This is a quickstart guide for rails apps. Firstly, install [cucumber-rails](http://github.com/aslakhellesoy/cucumber-rails), and its dependencies. Then do the following:
12
+
13
+ ### Rails 3:
14
+
15
+ Add the gem to your Gemfile:
16
+
17
+ ```ruby
18
+ gem 'pickle'
19
+ ```
20
+
21
+ Then install with:
22
+
23
+ ```shell
24
+ bundle install
25
+ ```
26
+
27
+ Discover the options for the generator:
28
+
29
+ ```shell
30
+ rails g pickle --help
31
+ ```
32
+
33
+ Run the generator, e.g:
34
+
35
+ ```shell
36
+ rails g pickle --paths --email
37
+ ```
38
+
39
+ ### For Rails 2:
40
+
41
+ Add the following to config/environments/cucumber:
42
+
43
+ ```ruby
44
+ config.gem 'pickle'
45
+ ```
46
+
47
+ Install the gem with
48
+
49
+ ```shell
50
+ rake gems:install RAILS_ENV=cucumber
51
+ ```
52
+
53
+ Run the generator with:
54
+
55
+ ```ruby
56
+ script/generate pickle [paths] [email]
57
+ ```
58
+
59
+ ## Resources
60
+
61
+ **GitHub** for code: https://github.com/ianwhite/pickle
62
+
63
+ **RubyGems** for the gem: https://rubygems.org/gems/pickle
64
+
65
+ **RubyDoc.info** for docs: http://www.rubydoc.info/github/ianwhite/pickle
66
+
67
+ **Google Group** for questions: https://groups.google.com/group/pickle-cucumber
68
+
69
+ **Railscast** presentation: http://railscasts.com/episodes/186-pickle-with-cucumber
70
+
71
+ **Blog articles**: [rubyflare: pickle my cucumber](http://rubyflare.com/2009/10/28/pickle-my-cucumber/)
72
+
73
+ ## Using Pickle
74
+
75
+ Now have a look at `features/step_definitions/pickle_steps.rb`
76
+
77
+ If you want path steps and email steps then just add the 'paths' and/or 'email' options to the generator. The code/steps will be written to `features/env/paths.rb` and `features/step_definitions/email_steps.rb` respectively.
78
+
79
+ ### Using with plain ole Active Record, DataMapper or Mongoid
80
+
81
+ Pickle comes with ORM adapters for Active Record, DataMapper and Mongoid.
82
+
83
+ If you have a model called 'Post', with required fields 'title', and 'body', then you can now write steps like this
84
+
85
+ ```gherkin
86
+ Given a post exists with title: "My Post", body: "My body"
87
+ ```
88
+
89
+ ### Using with factory-girl or machinist
90
+
91
+ But you're using Machinist or FactoryGirl right?! To leverage all of the factories/blueprints you've written, you can just do stuff like
92
+
93
+ ```gherkin
94
+ Given a user exists
95
+ And another user exists with role: "admin"
96
+
97
+ # later
98
+ Then a user should exist with name: "Fred"
99
+ And that user should be activated # this uses rspec predicate matchers
100
+ ```
101
+
102
+ #### Machinist: require your blueprints
103
+
104
+ In your `features/support/env.rb` add the following lines at the bottom
105
+
106
+ ```ruby
107
+ require "#{Rails.root}/spec/blueprints" # or wherever they live
108
+ ```
109
+
110
+ #### FactoryGirl: make sure factories are loaded
111
+
112
+ In your config/environments/cucumber.rb file, make sure the factory-girl gem is included (unless it's installed as a plugin).
113
+
114
+ If that doesn't solve loading issues then require your factories.rb file directly in a file called 'features/support/factory_girl.rb'
115
+
116
+ ```ruby
117
+ # example features/support/factory_girl.rb
118
+ require File.dirname(__FILE__) + '/../../spec/factories'
119
+ ```
120
+
121
+ ### Using with an ORM other than ActiveRecord, DataMapper, or Mongoid
122
+
123
+ Pickle can be used with any modelling library provided there is an adapter written for it.
124
+
125
+ Adapters are very simple and exist a module or class with the name "PickleAdapter" available to the class. For example
126
+
127
+ ```ruby
128
+ User.const_get(:PickleAdapter) #=> should return a pickle adapter
129
+ ```
130
+
131
+ The Active Record and DataMapper ones can be found at ActiveRecord::Base::PickleAdapter, DataMapper::Resource::PickleAdapter, Mongoid::Document::PickleAdapter respectively.
132
+
133
+ See how to implement one by looking at the ones provided in the pickle source in lib/pickle/adapters/\*
134
+
135
+ ### Configuring Pickle
136
+
137
+ You can tell pickle to use another factory adapter (see Pickle::Adapter), or create mappings from english expressions to pickle model names. You can also override many of the options on the Pickle::Config object if you so choose.
138
+
139
+ In: `features/support/pickle.rb`
140
+
141
+ ```ruby
142
+ require 'pickle/world'
143
+
144
+ Pickle.configure do |config|
145
+ config.adapters = [:machinist, :active_record, YourOwnAdapterClass]
146
+ config.map 'me', 'myself', 'my', 'I', :to => 'user: "me"'
147
+ end
148
+ ```
149
+
150
+ Out of the box pickle looks for machinist, factory-girl, then uses the ORM(s) that you're using to create models.
151
+
152
+ If you find that your steps aren't working with your factories, it's probably the case that your factory setup is not being included in your cucumber environment (see comments above regarding machinist and factory-girl).
153
+
154
+ ## API
155
+
156
+ ### Steps
157
+
158
+ When you run `script/generate pickle` you get the following steps
159
+
160
+ #### Given steps
161
+
162
+ "Given **a model** exists", e.g.
163
+
164
+ ```gherkin
165
+ Given a user exists
166
+ Given a user: "fred" exists
167
+ Given the user exists
168
+ ```
169
+
170
+ "Given **a model** exists with **fields**", e.g.
171
+
172
+ ```gherkin
173
+ Given a user exists with name: "Fred"
174
+ Given a user exists with name: "Fred", activated: false
175
+ ```
176
+
177
+ This last step could be better expressed by using Machinist/FactoryGirl to create an activated user. Then you can do
178
+
179
+ ```gherkin
180
+ Given an activated user exists with name: "Fred"
181
+ ```
182
+
183
+ You can refer to other models in the fields
184
+
185
+ ```gherkin
186
+ Given a user exists
187
+ And a post exists with author: the user
188
+
189
+ Given a person "fred" exists
190
+ And a person "ethel" exists
191
+ And a fatherhood exists with parent: person "fred", child: person "ethel"
192
+ ```
193
+
194
+ This last step is given by the default pickle steps, but it would be better written as:
195
+
196
+ ```gherkin
197
+ And "fred" is the father of "ethel"
198
+ ```
199
+
200
+ It is expected that you'll need to expand upon the default pickle steps to make your features readable. To write the above step, you could do something like:
201
+
202
+ ```ruby
203
+ Given /^"(\w+)" is the father of "(\w+)"$/ do |father, child|
204
+ Fatherhood.create! :father => model!("person: \"#{father}\""), :child => model!("person: \"#{child}\"")
205
+ end
206
+ ```
207
+
208
+ "Given **n models** exist", e.g.
209
+
210
+ ```gherkin
211
+ Given 10 users exist
212
+ ```
213
+
214
+ "Given **n models** exist with **fields**", examples:
215
+
216
+ ```gherkin
217
+ Given 10 users exist with activated: false
218
+ ```
219
+
220
+ "Given the following **models** exist:", examples:
221
+
222
+ ```gherkin
223
+ Given the following users exist
224
+ | name | activated |
225
+ | Fred | false |
226
+ | Ethel | true |
227
+ ```
228
+
229
+ ##### Named machinist blueprints
230
+
231
+ "Given **a _named_ model** exists with **fields**"
232
+
233
+ The latest version of pickle supports [named machinist blueprints](http://github.com/notahat/machinist/commit/d6492e6927a8aa1819926e48b22377171fd20496).
234
+
235
+ If you had the following blueprints:
236
+
237
+ ```ruby
238
+ User.blueprint do
239
+ name
240
+ email
241
+ end
242
+
243
+ User.blueprint(:super_admin) do
244
+ role { "admin" }
245
+ end
246
+
247
+ User.blueprint(:activated) do
248
+ activated { true }
249
+ end
250
+ ```
251
+
252
+ You could create a user with pickle by simply adding the name of the blueprint before the model:
253
+
254
+ ```gherkin
255
+ Given a super admin user exists
256
+ And an activated user exists with name: "Fred"
257
+ ```
258
+
259
+ This is much nicer than having to set up common configurations in your steps all the time, and far more readable to boot.
260
+
261
+ #### Then steps
262
+
263
+ ##### Asserting existence of models
264
+
265
+ "Then **a model** should exist", e.g.
266
+
267
+ ```gherkin
268
+ Then a user should exist
269
+ ```
270
+
271
+ "Then **a model** should exist with **fields**", e.g.
272
+
273
+ ```gherkin
274
+ Then a user: "fred" should exist with name: "Fred" # we can label the found user for later use
275
+ ```
276
+
277
+ You can use other models, booleans, numerics, and strings as fields
278
+
279
+ ```gherkin
280
+ Then a person should exist with child: person "ethel"
281
+ Then a user should exist with activated: false
282
+ Then a user should exist with activated: true, email: "fred@gmail.com"
283
+ ```
284
+
285
+ "Then **n models** should exist", e.g.
286
+
287
+ ```gherkin
288
+ Then 10 events should exist
289
+ ```
290
+
291
+ "Then **n models** should exist with **fields**", e.g.
292
+
293
+ ```gherkin
294
+ Then 2 people should exist with father: person "fred"
295
+ ```
296
+
297
+ "Then the following **models** exist". This allows the creation of multiple models using a table syntax. Using a column with the singularized name of the model creates a referenceable model. E.g.
298
+
299
+ ```gherkin
300
+ Then the following users exist:
301
+ | name | activated |
302
+ | Freddy | false |
303
+
304
+ Then the following users exist:
305
+ | user | name | activated |
306
+ | Fred | Freddy | false |
307
+ ```
308
+
309
+ ##### Asserting associations
310
+
311
+ One-to-one assocs: "Then **a model** should be **other model**'s **association**", e.g.
312
+
313
+ ```gherkin
314
+ Then the person: "fred" should be person: "ethel"'s father
315
+ ```
316
+
317
+ Many-to-one assocs: "Then **a model** should be [in|one of] **other model**'s **association**", e.g.
318
+
319
+ ```gherkin
320
+ Then the person: "ethel" should be one of person: "fred"'s children
321
+ Then the comment should be in the post's comments
322
+ ```
323
+
324
+ ##### Asserting predicate methods
325
+
326
+ "Then **a model** should [be|have] [a|an] **predicate**", e.g.
327
+
328
+ ```gherkin
329
+ Then the user should have a status # => user.status.should be_present
330
+ Then the user should have a stale password # => user.should have_stale_password
331
+ Then the car: "batmobile" should be fast # => car.should be_fast
332
+ ```
333
+
334
+ "Then **a model** should not [be|have] [a|an] **predicate**", e.g.
335
+
336
+ ```gherkin
337
+ Then person: "fred" should not be childless # => fred.should_not be_childless
338
+ ```
339
+
340
+ ### Regexps for use in your own steps
341
+
342
+ By default you get some regexps available in the main namespace for use in creating your own steps: `capture_model`, `capture_fields`, and others (see lib/pickle.rb)
343
+
344
+ (You can use any of the regexps that Pickle uses by using the Pickle.parser namespace, see Pickle::Parser::Matchers for the methods available)
345
+
346
+ **capture_model**
347
+
348
+ ```ruby
349
+ Given /^#{capture_model} exists$/ do |model_name|
350
+ model(model_name).should_not == nil
351
+ end
352
+
353
+ Then /^I should be at the (.*?) page$/ |page|
354
+ if page =~ /#{capture_model}'s/
355
+ url_for(model($1))
356
+ else
357
+ # ...
358
+ end
359
+ end
360
+
361
+ Then /^#{capture_model} should be one of #{capture_model}'s posts$/ do |post, forum|
362
+ post = model!(post)
363
+ forum = model!(forum)
364
+ forum.posts.should include(post)
365
+ end
366
+ ```
367
+
368
+ **capture_fields**
369
+
370
+ This is useful for setting attributes, and knows about pickle model names so that you can build up composite objects with ease
371
+
372
+ ```ruby
373
+ Given /^#{capture_model} exists with #{capture_fields}$/ do |model_name, fields|
374
+ create_model(model_name, fields)
375
+ end
376
+
377
+ # example of use
378
+ Given a user exists
379
+ And a post exists with author: the user # this step will assign the above user as :author on the post
380
+ ```
381
+
382
+ ### Email Steps
383
+
384
+ When you run `rails g pickle --email` you get steps for handling email.
385
+
386
+ The general pattern of use is to clear the email queue (if necessary), have your app perform something that sends emails, assert that emails have been delivered, then assert those emails have particular properties.
387
+
388
+ For example:
389
+
390
+ ```gherkin
391
+ Background:
392
+ Given a user has signed up
393
+ And all emails have been delivered
394
+ And the user has signed in
395
+
396
+ Scenario: User buys a fork
397
+ Given I am on the fork page
398
+ And I press "Buy Fork!"
399
+ Then 1 email should be delivered to the user
400
+ And the email should contain "You can haz Fork!"
401
+ When I follow the "my account" link in the email
402
+ Then I should be on the account page
403
+
404
+ And 1 email should be delivered to "sales@example.com"
405
+ And the email should contain the user's page
406
+ And the email should contain "User can haz Fork!"
407
+ ```
408
+
409
+ You can refer to emails that were found in the `Then *n* emails should be delivered` in the following ways:
410
+
411
+ ```gherkin
412
+ the email (refers to last email)
413
+ the 1st email
414
+ the last email
415
+ email to: "joe@example.com"
416
+ email subject: "some subject"
417
+ email to: "joe@example.com", subject: "some subject"
418
+ ```
419
+
420
+ #### Map expressions to email addresses
421
+
422
+ By default a step like
423
+
424
+ ```gherkin
425
+ Then 2 emails should be delivered to the user "Ethel"
426
+ ```
427
+
428
+ Will look for the `email` attribute on the found model. This is configurable in much the same way as page names for url paths. Have a look at `features/support/email.rb` to add your own custom mappings.
429
+
430
+ For example:
431
+
432
+ ```ruby
433
+ # in features/support/email.rb
434
+ when /^#{capture_model} sales team$/
435
+ model!($1).sales_email
436
+
437
+ # in a feature
438
+ Given a site exists
439
+ And someone buys something form the site
440
+ Then 1 email should be delivered to the site sales team
441
+ ```
442
+
443
+ More detail on the emails steps follows:
444
+
445
+ #### Given steps
446
+
447
+ Clear the email queue, e.g.
448
+
449
+ ```gherkin
450
+ Given all email has been delivered
451
+ Given all emails have been delivered
452
+ ```
453
+
454
+ #### When steps
455
+
456
+ When **[I|they]** follow **[text_or_regex|the first link]** the email, e.g.
457
+
458
+ ```gherkin
459
+ When I click the first link in the email
460
+ When I follow "http://example.com/pickle" in the email
461
+ When I follow "some link text" in the email
462
+ ```
463
+
464
+ #### Then steps
465
+
466
+ Then **n** email(s) should be delivered to **address**, e.g.
467
+
468
+ ```gherkin
469
+ Then 1 email should be delivered to joe@example.com
470
+ ```
471
+
472
+ Then **n** email(s) should be delivered with **fields**, e.g.
473
+
474
+ ```gherkin
475
+ Then 2 emails should be delivered with subject: "Welcome to pickle"
476
+ Then 2 email should be delivered with to: "joe@example.com", from: "pickle@example.com"
477
+ ```
478
+
479
+ Then **fields** should be delivered to **address**, e.g.
480
+
481
+ ```gherkin
482
+ Then subject: "Welcome to pickle" should be delivered to joe@example.com
483
+ ```
484
+
485
+ Then **fields** should be not delivered to **address**, e.g.
486
+
487
+ ```gherkin
488
+ Then subject: "Welcome to pickle" should not be delivered to pickle@example.com
489
+ ```
490
+
491
+ Then **email** should have **fields**, e.g.
492
+
493
+ ```gherkin
494
+ Then the email should have subject: "Welcome to pickle", from: "pickle@example.com"
495
+ ```
496
+
497
+ Then **email** should contain "**text**", e.g.
498
+
499
+ ```gherkin
500
+ Then the email should contain "Thank you for choosing pickle"
501
+ ```
502
+
503
+ Then **email** should not contain "**text**", e.g.
504
+
505
+ ```gherkin
506
+ Then the email should not contain "v1@gr@"
507
+ ```
508
+
509
+ Then **email** should link to "**href**", e.g.
510
+
511
+ ```gherkin
512
+ Then the email should link to http://example.com/pickle
513
+ ```
514
+
515
+ Then show me the email(s), will open the email(s) in your browser (depends on OS X)
516
+
517
+ ```gherkin
518
+ Then show me the email(s)
519
+ ```
520
+
521
+ ## Run the tests
522
+
523
+ To run the specs and features, you can start from the last known good set of gem dependencies in Gemfile.lock.development:
524
+
525
+ ```ruby
526
+ git clone http://github.com/ianwhite/pickle
527
+ cd pickle
528
+ cp Gemfile.lock.development Gemfile.lock
529
+ bundle
530
+ ```
531
+
532
+ To run the specs & features do:
533
+
534
+ ```ruby
535
+ bundle exec rake spec
536
+ bundle exec rake cucumber
537
+ ```
538
+
539
+ ## Contributors
540
+
541
+ The following people have made Pickle better:
542
+
543
+ * [Jules Copeland](http://github.com/julescopeland)
544
+ * [David Padilla](http://github.com/dabit)
545
+ * [Ari Epstein](http://github.com/aepstein)
546
+ * [Jonathan Hinkle](http://github.com/hynkle)
547
+ * [Devin Walters and Nick Karpenske](http://github.com/bendyworks)
548
+ * [Marc Lee](http://github.com/maleko)
549
+ * [Sebastian Zuchmanski](http://github.com/sebcioz)
550
+ * [Paul Gideon Dann](http://github.com/giddie)
551
+ * [Tom Meier](http://github.com/tommeier)
552
+ * [Sean Hussey](http://github.com/seanhussey)
553
+ * Brian Rose & Kevin Olsen
554
+ * [Christopher Darroch](http://github.com/chrisdarroch)
555
+ * [Szymon Nowak](http://github.com/szimek)
556
+ * [H.J. Blok](http://github.com/hjblok)
557
+ * [Daniel Neighman](http://github.com/hassox)
558
+ * [Josh Bassett](http://github.com/nullobject)
559
+ * [Nick Rutherford](http://github.com/nruth)
560
+ * [Tobi Knaup](http://github.com/guenter)
561
+ * [Michael MacDonald](http://github.com/schlick)
562
+ * [Michael Moen](http://github.com/UnderpantsGnome)
563
+ * [Myron Marston](http://github.com/myronmarston)
564
+ * [Stephan Hagemann](http://github.com/xing)
565
+ * [Chris Flipse](http://github.com/cflipse)
566
+ * [Jon Kinney](http://github.com/jondkinney)