rspec-tapas 0.1.0 → 0.2.0

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: 02d482bfe50d7a8b18f7b7b4c4fca20f55072bb0
4
- data.tar.gz: 13460e4cb8ae5f5879c47a909fe855128bc7267b
3
+ metadata.gz: ac612ac4ea7957a55f94f98fe712c54e47d0e1c0
4
+ data.tar.gz: e588c6af989d560c2979566309555d4954031029
5
5
  SHA512:
6
- metadata.gz: 0b635329022669a7a7974a00c5b8b6d8802bc98524c736235855c98249db545db181d2afb3646997904e871a408a1336d1e59fa5ce895a3134314a4e8cea702d
7
- data.tar.gz: a7541cb38c463665e958fc46c738a4d29b180e95825ba7f1a71b2244166aaa007d92866aa55644637eff5dff68a165e3a8abd4ec459ff56b51e5ea21685d25b4
6
+ metadata.gz: 063ab3599b8834d5a79864716c0ae2c2159c95b604f57351fac1fe19899afc7fe3b03b72131053cb97b3279871bd8d064a4f8f90b3c23382e12b85d063a92f28
7
+ data.tar.gz: 773b4f7ffc6013d08f8eb6ce59d8d89c6e3f715222575a2fea861b123a0d19f370f44adab00e215545f36f1cc8dd2b2e32c86084ab32f4b960ff9a7754e49b61
@@ -0,0 +1,304 @@
1
+ # rspec-tapas
2
+
3
+ rspec-tapas is a set of small helpers and extensions we often use in [Selleo](https://selleo.com/) when testing our ruby apps.
4
+
5
+ ## Installation
6
+
7
+ To install rspec-tapas just add following line to your `Gemfile`s `:test` group
8
+
9
+ ```ruby
10
+ gem 'ruby-tapas'
11
+ ```
12
+
13
+ then just `bundle install` and require it in `rails_helper.rb`
14
+
15
+ ```ruby
16
+ require 'rspec_tapas/all'
17
+ ```
18
+
19
+ ## Helpers
20
+
21
+ ### StubEnv
22
+
23
+ `StubEnv` is an extension that allows you to quickly stub values that should be retrieved from `ENV`.
24
+ It is assumed here, that you will use `fetch` method to retrieve such value (so it yields an exception when given ENV is not defined what sounds like a reasonable default).
25
+
26
+ *Example*
27
+
28
+ ```ruby
29
+ it 'sends a notification after checkout' do
30
+ stub_env('CHECKOUT_TIME', '13:00')
31
+ #...
32
+ end
33
+ ```
34
+
35
+ To include this extension only, call `require rspec_tapas/stub_env`
36
+
37
+ `StubEnv` is accessible in all types of specs
38
+
39
+ ### DateHelpers
40
+
41
+ `DateHelpers` is a set of two methods that facilitate using `ActiveSupport::Testing::TimeHelpers`. Therefore you need to include `ActiveSupport::Testing::TimeHelpers` in your config if you want to use `DateHelpers`. It is as simple as
42
+
43
+ ```ruby
44
+ RSpec.configure do |config|
45
+ config.include ActiveSupport::Testing::TimeHelpers
46
+ end
47
+ ```
48
+
49
+ #### at_date
50
+
51
+ `at_date` runs contents of the block at given date, provided in a format acceptable by `Date.new`. It is basically a shortcut to `travel_to(Date.new(*args)){}`.
52
+
53
+ *Example*
54
+
55
+ ```ruby
56
+ context 'one day before deadline' do
57
+ it 'sends a reminder' do
58
+ #...
59
+ at_date(2018, 1, 12) do
60
+ SendPendingReminders.call
61
+ end
62
+ #...
63
+ end
64
+ end
65
+ ```
66
+
67
+ #### freeze_time
68
+
69
+ `freeze_time` freezes the time and runs contents of the block at. It is basically a shortcut to `travel_to(Time.current){}`.
70
+
71
+ *Example*
72
+
73
+ ```ruby
74
+ it 'discards records created at the same time' do
75
+ #...
76
+ freeze_time do
77
+ user_1 = create(:user)
78
+ user_2 = create(:user)
79
+ end
80
+ #...
81
+ end
82
+ ```
83
+
84
+ To include this extension only, call `require rspec_tapas/date_helpers`
85
+
86
+ `DateHelpers` are accessible in all types of specs
87
+
88
+ ### ViewPage
89
+
90
+ `ViewPage` is a small helper that allows testing views using capybara helpers, usually limited only to feature specs.
91
+
92
+ *Example*
93
+
94
+ ```ruby
95
+ RSpec.describe 'users/show.html.erb', type: :view do
96
+ it 'renders user name' do
97
+ user = create(:user, name: "Tony")
98
+ allow(view).to receive(:user) { user }
99
+
100
+ render
101
+
102
+ expect(page).to have_content("Tony")
103
+ end
104
+ end
105
+ ```
106
+
107
+ To include this extension only, call `require rspec_tapas/view_page`
108
+
109
+ `ViewPage` is accessible only in view specs
110
+
111
+
112
+ ### InvokeTask
113
+
114
+ `InvokeTask` is a small helper that facilitates calling rake tasks when testing them.
115
+
116
+ *Example*
117
+
118
+ ```ruby
119
+ RSpec.describe 'db:materialize', type: :rake do
120
+ it 'materializes db view by name' do
121
+ database = double(:database)
122
+ allow(Scenic).to receive(:database) { database }
123
+ allow(database).to receive(:refresh_materialized_view)
124
+
125
+ invoke_task('db:materialize', view_name: 'sample_view')
126
+
127
+ expect(database).to \
128
+ have_received(:refresh_materialized_view).with('sample_view')
129
+ end
130
+ end
131
+ ```
132
+
133
+ To include this extension only, call `require rspec_tapas/invoke_task`
134
+
135
+ `InvokeTask` is accessible only in rake specs
136
+
137
+
138
+ ### GetMessagePart
139
+
140
+ `GetMessagePart` is a set of helpers to facilitate extraction of html/plain parts of emails sent. To extract plaintext part from email, use `text_part(mail)`. To extract HTML part, use `html_part(mail)`.
141
+
142
+ ```ruby
143
+ RSpec.describe ReportMailer, type: :mailer do
144
+ describe '#summary' do
145
+ it 'creates email containing orders summary' do
146
+ create_list(:order, 2)
147
+ mail = ReportMailer.summary
148
+
149
+ expect(mail.subject).to eq('Orders summary')
150
+ expect(html_part(mail)).to include_html(
151
+ <<~HTML
152
+ <h1>Orders summary</h1>
153
+ <strong>Total orders created:</strong> 2 <br />
154
+ HTML
155
+ )
156
+ expect(text_part(mail)).to include('Total orders created: 2')
157
+ end
158
+ end
159
+ end
160
+ ```
161
+
162
+ To include this extension only, call `require rspec_tapas/get_message_part`
163
+
164
+ `GetMessagePart` is accessible only in mailer specs
165
+
166
+ ### JsonResponse
167
+
168
+ `JsonResponse` is a simple helper that transforms JSON encoded response body to `HashWithIndifferentAccess` or an array of those. This is to facilitate using regular matchers to assert such response.
169
+
170
+ *Example*
171
+
172
+ ```ruby
173
+ it 'returns user names and emails' do
174
+ create(:user, name: 'Tony', email: 'tony@stark.dev')
175
+ create(:user, name: 'Bruce', email: 'bruce@wayne.dev')
176
+
177
+ get '/v1/users'
178
+
179
+ expect(json_response).to match(
180
+ data: [
181
+ { name: 'Tony', email: 'tony@stark.dev' },
182
+ { name: 'Bruce', email: 'bruce@wayne.dev' },
183
+ ]
184
+ )
185
+ end
186
+ ```
187
+
188
+ To include this extension only, call `require rspec_tapas/json_response`
189
+
190
+ `JsonResponse` is accessible only in request and controller specs
191
+
192
+ ### DownloadsHelpers
193
+
194
+ `DownloadsHelpers` is a set of two helpers oriented on facilitating testing downloads. First, we need to allow downloading file in given feature spec by calling `allow_file_downloads(page)`. Then, to get downloaded file contents, we need to use `downloaded_file_contents(file_name)` helper.
195
+
196
+ To allow downloads with headless-chrome capybara driver, we need to configure it in specific way. See example below:
197
+
198
+ ```ruby
199
+ require 'selenium/webdriver'
200
+
201
+ Capybara.register_driver :headless_chrome do |app|
202
+ options = Selenium::WebDriver::Chrome::Options.new
203
+ options.add_argument('--headless')
204
+ options.add_argument('--no-sandbox')
205
+ options.add_argument('--disable-gpu')
206
+ options.add_argument('--disable-popup-blocking')
207
+ options.add_argument('--window-size=1920,1200')
208
+ options.add_preference(
209
+ :download,
210
+ directory_upgrade: true,
211
+ prompt_for_download: false,
212
+ default_directory: RspecExtensions::DownloadsHelpers::DOWNLOADS_PATH
213
+ )
214
+ options.add_preference(:browser, set_download_behavior: { behavior: 'allow' })
215
+
216
+ Capybara::Selenium::Driver.new(app, browser: :chrome, options: options)
217
+ end
218
+
219
+ Capybara.javascript_driver = :headless_chrome
220
+ ```
221
+
222
+ Then, testing downloads is just a matter of few lines of code.
223
+
224
+ *Example*
225
+
226
+ ```ruby
227
+ allow_file_downloads(page)
228
+
229
+ click_on 'Download report'
230
+
231
+ expect(downloaded_file_contents('daily_report.csv')).to eq("Name, Total revenue\nBatman suits, 1000")
232
+ ```
233
+
234
+ To include this extension only, call `require rspec_tapas/downloads_helpers`
235
+
236
+ `DownloadsHelpers` are accessible only in feature specs
237
+
238
+ ### FeatureHelpers
239
+
240
+ `FeatureHelpers` module contains a couple of methods useful in features specs.
241
+
242
+ - `display_logs` will display browser logs in console. This is useful for debugging javascript errors in feature specs.
243
+ - `ss` is a shortcut for `page.save_and_open_screenshot`
244
+ - `reload_page` is a handy shortcut for reloading current page.
245
+
246
+ To include this extension only, call `require rspec_tapas/feature_helpers`
247
+
248
+ `FeatureHelpers` are accessible only in feature specs
249
+
250
+ ### BehaviorDSL
251
+
252
+ `BehaviorDSL` module has two roles. First one is to add some syntactic sugar to feature specs, by introducing additional level of describing context, but without interrupting test. This way you can group actions and assertions in readable blocks.
253
+
254
+ Second role of `BehaviorDSL` is to add capability of asserting feature - controller integration. This way we can ensure, that given block of capybara interactions were using particular controller action.
255
+
256
+ *Example*
257
+
258
+ ```ruby
259
+ RSpec.describe 'Users management' do
260
+ scenario do
261
+ behavior 'Admin browses existing users', using: 'Admin::UsersController#index' do
262
+ create(:user, name: 'Luke Cage')
263
+ create(:unit, name: 'Jessica Jones')
264
+
265
+ visit '/admin/users'
266
+
267
+ expect(page).to have_row_content('Full name' => 'Luke Cage')
268
+ expect(page).to have_row_content('Full name' => 'Jessica Jones')
269
+ end
270
+
271
+ behavior 'Admin updates existing user' do
272
+ #...
273
+ end
274
+ end
275
+ end
276
+ ```
277
+
278
+ To include this extension only, call `require rspec_tapas/behavior_dsl`
279
+
280
+ `BehaviorDSL` is accessible only in feature specs
281
+
282
+ ## Matchers
283
+
284
+ ### have_table_row
285
+
286
+ `have_table_row` is a matcher dedicated to finding table rows by their values correlated with specific headers. As so, this is mostly useful in feature specs.
287
+
288
+ *Examples*
289
+
290
+ ```ruby
291
+ # Asserting headers by their names
292
+ expect(page).to have_table_row('First name' => 'Tony', 'Last name' => 'Stark', 'Rating' => 4.5)
293
+
294
+ # Asserting headers by their indices
295
+ expect(page).to have_table_row(1 => 'Tony', 2 => 'Stark', 3 => 4.5)
296
+
297
+ # Asserting headers by their indices - shorter version
298
+ expect(page).to have_table_row('Tony', 'Stark', 4.5)
299
+
300
+ # Composing matchers
301
+ expect(page).to have_table_row(have_content('ny'), 'Stark')
302
+ ```
303
+
304
+ To include this matcher only, call `require rspec_tapas/matchers/have_table_row`
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.0
1
+ 0.2.0
@@ -1,24 +1,40 @@
1
1
  module RspecExtensions
2
2
  module BehaviorDSL
3
- def behavior(name)
4
- metadata[:description_args].push(name)
5
- refresh_description
6
- yield
7
- metadata[:description_args].pop
8
- refresh_description
3
+ BehaviorNotification = Struct.new(:message)
4
+ class BehaviorNotification
5
+ def execution_result
6
+ RSpec::Core::Example::ExecutionResult.new
7
+ end
8
+
9
+ def description
10
+ message
11
+ end
9
12
  end
10
13
 
11
- private
14
+ def behavior(name, using: nil)
15
+ if using.present?
16
+ @controller_actions_called = []
17
+ callback = lambda do |*args|
18
+ options = args.extract_options!
19
+ @controller_actions_called << "#{options[:controller]}##{options[:action]}"
20
+ end
21
+ ActiveSupport::Notifications.subscribed(callback, 'start_processing.action_controller') do
22
+ yield
23
+ end
24
+
25
+ expect(@controller_actions_called).to(
26
+ include(using),
27
+ "expected #{using} to be used for #{name}, but it was not"
28
+ )
29
+ else
30
+ yield
31
+ end
12
32
 
13
- def refresh_description
14
- metadata[:description] = metadata[:description_args].join(' ')
15
- metadata[:full_description] = \
16
- [metadata[:example_group][:full_description]].
17
- concat(metadata[:description_args]).join(' ')
33
+ reporter.example_passed(BehaviorNotification.new(name))
18
34
  end
19
35
 
20
- def metadata
21
- RSpec.current_example.metadata
36
+ def reporter
37
+ RSpec.current_example.reporter
22
38
  end
23
39
  end
24
40
  end
@@ -2,28 +2,28 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Juwelier::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
- # stub: rspec-tapas 0.1.0 ruby lib
5
+ # stub: rspec-tapas 0.2.0 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "rspec-tapas".freeze
9
- s.version = "0.1.0"
9
+ s.version = "0.2.0"
10
10
 
11
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
12
12
  s.require_paths = ["lib".freeze]
13
13
  s.authors = ["B\u0142a\u017Cej Kosmowski".freeze]
14
- s.date = "2018-06-26"
14
+ s.date = "2018-06-27"
15
15
  s.description = "A selection of small rSpec extensions".freeze
16
16
  s.email = "b.kosmowski@selleo.com".freeze
17
17
  s.extra_rdoc_files = [
18
18
  "LICENSE.txt",
19
- "README.rdoc"
19
+ "README.md"
20
20
  ]
21
21
  s.files = [
22
22
  ".document",
23
23
  "Gemfile",
24
24
  "Gemfile.lock",
25
25
  "LICENSE.txt",
26
- "README.rdoc",
26
+ "README.md",
27
27
  "Rakefile",
28
28
  "VERSION",
29
29
  "lib/rspec-tapas.rb",
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec-tapas
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Błażej Kosmowski
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-06-26 00:00:00.000000000 Z
11
+ date: 2018-06-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: shoulda
@@ -86,13 +86,13 @@ executables: []
86
86
  extensions: []
87
87
  extra_rdoc_files:
88
88
  - LICENSE.txt
89
- - README.rdoc
89
+ - README.md
90
90
  files:
91
91
  - ".document"
92
92
  - Gemfile
93
93
  - Gemfile.lock
94
94
  - LICENSE.txt
95
- - README.rdoc
95
+ - README.md
96
96
  - Rakefile
97
97
  - VERSION
98
98
  - lib/rspec-tapas.rb
@@ -1,18 +0,0 @@
1
- = rspec-tapas
2
-
3
- Description goes here.
4
-
5
- == Contributing to rspec-tapas
6
-
7
- * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
8
- * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
9
- * Fork the project.
10
- * Start a feature/bugfix branch.
11
- * Commit and push until you are happy with your contribution.
12
- * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
13
- * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
14
-
15
- == Copyright
16
-
17
- Copyright (c) 2018 Błażej Kosmowski. See LICENSE.txt for
18
- further details.