rails_stuff 0.5.1 → 0.6.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/CHANGELOG.md +29 -0
- data/Gemfile +1 -0
- data/README.md +37 -16
- data/gemfiles/rails_4.gemfile +1 -0
- data/gemfiles/rails_5.gemfile +1 -0
- data/lib/rails_stuff/engine.rb +1 -1
- data/lib/rails_stuff/resources_controller/actions.rb +3 -3
- data/lib/rails_stuff/resources_controller/basic_helpers.rb +1 -1
- data/lib/rails_stuff/resources_controller/resource_helper.rb +32 -14
- data/lib/rails_stuff/resources_controller.rb +0 -2
- data/lib/rails_stuff/responders/turbolinks.rb +13 -0
- data/lib/rails_stuff/responders.rb +19 -0
- data/lib/rails_stuff/rspec_helpers/concurrency.rb +45 -0
- data/lib/rails_stuff/rspec_helpers/groups/feature.rb +25 -0
- data/lib/rails_stuff/rspec_helpers/groups/request.rb +79 -0
- data/lib/rails_stuff/rspec_helpers/matchers/be_valid_js.rb +12 -0
- data/lib/rails_stuff/rspec_helpers/matchers/redirect_with_turbolinks.rb +53 -0
- data/lib/rails_stuff/rspec_helpers/signinable.rb +21 -0
- data/lib/rails_stuff/rspec_helpers.rb +123 -0
- data/lib/rails_stuff/sort_scope.rb +19 -0
- data/lib/rails_stuff/statusable/builder.rb +114 -0
- data/lib/rails_stuff/statusable/helper.rb +64 -0
- data/lib/rails_stuff/statusable/mapped_builder.rb +48 -0
- data/lib/rails_stuff/statusable/mapped_helper.rb +46 -0
- data/lib/rails_stuff/statusable.rb +53 -199
- data/lib/rails_stuff/test_helpers/concurrency.rb +1 -32
- data/lib/rails_stuff/test_helpers/integration_session.rb +18 -0
- data/lib/rails_stuff/test_helpers/response.rb +10 -0
- data/lib/rails_stuff/test_helpers.rb +50 -0
- data/lib/rails_stuff/types_tracker.rb +1 -1
- data/lib/rails_stuff/version.rb +13 -3
- data/lib/rails_stuff.rb +3 -0
- metadata +20 -8
- data/lib/rails_stuff/resources_controller/responder.rb +0 -21
- data/lib/rails_stuff/test_helpers/configurator.rb +0 -60
- data/lib/rails_stuff/test_helpers/rails.rb +0 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 56cd33390b1d0c5cce251aba39698ef115de3c6c
|
4
|
+
data.tar.gz: 8e7032d8717fae0d1fa44c5f6ea308a150a2e73f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9abf798f564088d2bb174e955efdf0cce9b47528b8f0dac7095516a35fcd11752772cd3d691266235698fd5281622db8ce9f5f9d32a3d66a75c8efde2c5da87c
|
7
|
+
data.tar.gz: 3dbbc5a6052014726fba018811d5615d9e9527e913fb14a492d615527f4bbe6bb5312815d55549e613e38c6103728447e7b558c8f1bbf630c18d65eb897bfc13
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,34 @@
|
|
1
1
|
## Unreleased
|
2
2
|
|
3
|
+
## 0.6.0.rc1
|
4
|
+
|
5
|
+
### Controllers
|
6
|
+
|
7
|
+
- Don't overwrite :location option if present.
|
8
|
+
- Don't overwrite responder and `respond_with`'s mimes.
|
9
|
+
- `#current_sort_scope` to access applied sorting rules.
|
10
|
+
- `.resource_helper` has `source` option, which accepts lambdas and strings.
|
11
|
+
`class` option is deprecated now in favour of `source`.
|
12
|
+
|
13
|
+
### Models
|
14
|
+
|
15
|
+
- Improved Statusable:
|
16
|
+
|
17
|
+
- Model are now clear from lot of helper methods.
|
18
|
+
There is single `statuses` method for statusable field which holds all helpers.
|
19
|
+
- `.select_options` supports `:only` option.
|
20
|
+
- Helpers to map/unmap values for mapped statuses from external code.
|
21
|
+
|
22
|
+
### Tests
|
23
|
+
|
24
|
+
- A lot of new test and rspec helpers and configs (see RSpecHelpers, TestHelpers).
|
25
|
+
- `RSpecHelpers.setup` & `TestHelpers.setup` to setup helpers instead of requiring
|
26
|
+
files. This methods accepts `only` & `except` options.
|
27
|
+
|
28
|
+
### Misc
|
29
|
+
|
30
|
+
- Use AR#update instead of #update_attributes.
|
31
|
+
|
3
32
|
## 0.5.1
|
4
33
|
|
5
34
|
Rails 5 support.
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -58,8 +58,7 @@ __[Helpers usage](#helpers-usage)__
|
|
58
58
|
|
59
59
|
- __Response__
|
60
60
|
`#json_body` to test json responses.
|
61
|
-
-
|
62
|
-
Provides useful basic configuration for RSpec.
|
61
|
+
- Useful RSpec configurations, helpers and matchers for better experience.
|
63
62
|
- __Concurrency__
|
64
63
|
Helpers for testing with concurrent requests.
|
65
64
|
|
@@ -166,6 +165,9 @@ has_sort_scope by: [:name, :created_at, :balance], default: [:name]
|
|
166
165
|
# - `sort=name&sort_desc=true`
|
167
166
|
# - `sort[name]&sort[created_at]`
|
168
167
|
# - `sort[name]&sort[created_at]=desc
|
168
|
+
|
169
|
+
# access current sort scope hash with
|
170
|
+
current_sort_scope # => {'name' => :desc} or {'name' => :asc, 'id' => :desc}
|
169
171
|
```
|
170
172
|
|
171
173
|
Requires `gem 'has_scope'`.
|
@@ -249,10 +251,12 @@ User.with_status(param[:status]).with_subscription_status(params[:subs_status])
|
|
249
251
|
Order.with_status(:confirmed)
|
250
252
|
|
251
253
|
# Translation & select helpers (requires activemodel_translation gem)
|
252
|
-
User.
|
254
|
+
User.statuses.translate(:active)
|
253
255
|
user.subscription_status_name # translates current status
|
254
|
-
User.
|
255
|
-
User.
|
256
|
+
User.statuses.select_options
|
257
|
+
User.subscription_statuses.select_options except: [:expired]
|
258
|
+
Order.statuses.map([:submitted, :delivered]) # => [1, 3]
|
259
|
+
Order.statuses.unmap([1, 3]) # => [:submitted, :delivered]
|
256
260
|
|
257
261
|
# Accessors
|
258
262
|
user.status = 'confirmed' or user.confirmed!
|
@@ -409,8 +413,13 @@ switch locales while rendering single view.
|
|
409
413
|
|
410
414
|
### Test helpers usage
|
411
415
|
|
412
|
-
Add `
|
416
|
+
Add `RailsStuff::RSpec.setup` to `rails_helper.rb` to load all the stuff or
|
417
|
+
pick from `rails_stuff/test_helpers/` and `rails_stuff/rspec`.
|
418
|
+
|
419
|
+
Please check the source for complete list of helpers, while this section is not
|
420
|
+
well-documented.
|
413
421
|
|
422
|
+
#### `json_body`
|
414
423
|
```ruby
|
415
424
|
assert_equal({'id' => 1, 'name' => 'John'}, response.json_body)
|
416
425
|
assert_equal('John', response.json_body['name'])
|
@@ -430,17 +439,29 @@ Use `json_body['key']` instead.
|
|
430
439
|
|
431
440
|
There is `Configurator` with useful RSpec configs:
|
432
441
|
|
442
|
+
#### RSpec configurations
|
443
|
+
|
433
444
|
```ruby
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
445
|
+
# Setup DatabaseCleaner with basic settings:
|
446
|
+
RailsStuff::RSpec.database_cleaner
|
447
|
+
|
448
|
+
# Flush redis after suite and exampes with `flush_redis: true`:
|
449
|
+
RailsStuff::RSpec.redis
|
450
|
+
|
451
|
+
# Run debugger after failed tests:
|
452
|
+
RailsStuff::RSpec.debug
|
453
|
+
|
454
|
+
# Clear log/test.log after suite:
|
455
|
+
RailsStuff::RSpec.clear_logs
|
456
|
+
|
457
|
+
# Raise errors from threads:
|
458
|
+
RailsStuff::RSpec.thread
|
459
|
+
|
460
|
+
# Raise errors for all missing I18n translation:
|
461
|
+
RailsStuff::RSpec.i18n
|
462
|
+
|
463
|
+
# Freeze time with for group/example with `:frozen_time` metadata (requires timecop gem):
|
464
|
+
RailsStuff::RSpec.frozen_time
|
444
465
|
```
|
445
466
|
|
446
467
|
### PluginManager
|
data/gemfiles/rails_4.gemfile
CHANGED
data/gemfiles/rails_5.gemfile
CHANGED
data/lib/rails_stuff/engine.rb
CHANGED
@@ -8,7 +8,7 @@ module RailsStuff
|
|
8
8
|
random_uniq_attr: :model,
|
9
9
|
statusable: :model,
|
10
10
|
resources_controller: [
|
11
|
-
:controller,
|
11
|
+
-> { defined?(::Responders) && :controller },
|
12
12
|
-> { ResourcesController.use_kaminari! if defined?(::Kaminari) },
|
13
13
|
],
|
14
14
|
sort_scope: -> { defined?(::HasScope) && :controller },
|
@@ -8,21 +8,21 @@ module RailsStuff
|
|
8
8
|
|
9
9
|
def create(options = {}, &block)
|
10
10
|
if create_resource
|
11
|
-
options[:location]
|
11
|
+
options[:location] ||= after_save_url
|
12
12
|
end
|
13
13
|
respond_with(resource, options, &block)
|
14
14
|
end
|
15
15
|
|
16
16
|
def update(options = {}, &block)
|
17
17
|
if update_resource
|
18
|
-
options[:location]
|
18
|
+
options[:location] ||= after_save_url
|
19
19
|
end
|
20
20
|
respond_with(resource, options, &block)
|
21
21
|
end
|
22
22
|
|
23
23
|
def destroy(options = {}, &block)
|
24
24
|
resource.destroy
|
25
|
-
options[:location]
|
25
|
+
options[:location] ||= after_destroy_url
|
26
26
|
flash_errors!
|
27
27
|
respond_with(resource, options, &block)
|
28
28
|
end
|
@@ -2,6 +2,15 @@ module RailsStuff
|
|
2
2
|
module ResourcesController
|
3
3
|
# Defines resource helper and finder method.
|
4
4
|
module ResourceHelper
|
5
|
+
class << self
|
6
|
+
def deprecation
|
7
|
+
@deprecation ||= begin
|
8
|
+
require 'active_support/deprecation'
|
9
|
+
ActiveSupport::Deprecation.new('0.7', 'RailsStuff')
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
5
14
|
# Defines protected helper method. Ex. for `:user`
|
6
15
|
#
|
7
16
|
# helper_method :user
|
@@ -12,26 +21,35 @@ module RailsStuff
|
|
12
21
|
#
|
13
22
|
# #### Options
|
14
23
|
#
|
15
|
-
# - `
|
24
|
+
# - `source` - class name or Proc returning relation, default to `resource_name.classify`.
|
16
25
|
# - `param` - param name, default to `resource_name.foreign_key`
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
param_key = options[:param] || resource_name.foreign_key
|
26
|
+
#
|
27
|
+
# rubocop:disable CyclomaticComplexity, PerceivedComplexity, AbcSize
|
28
|
+
def resource_helper(name, param: nil, source: nil, **options)
|
29
|
+
ResourceHelper.deprecation.warn('use :source instead of :class') if options.key?(:class)
|
22
30
|
|
23
|
-
|
24
|
-
|
31
|
+
param ||= name.to_s.foreign_key.to_sym
|
32
|
+
define_method("#{name}?") { params.key?(param) }
|
25
33
|
|
26
|
-
|
27
|
-
|
34
|
+
ivar = :"@#{name}"
|
35
|
+
source ||= options[:class] || name.to_s.classify
|
36
|
+
if source.is_a?(Proc)
|
37
|
+
define_method(name) do
|
38
|
+
instance_variable_get(ivar) ||
|
39
|
+
instance_variable_set(ivar, instance_exec(&source).find(params[param]))
|
28
40
|
end
|
29
|
-
|
30
|
-
|
31
|
-
|
41
|
+
else
|
42
|
+
source = Object.const_get(source) unless source.is_a?(Class)
|
43
|
+
define_method(name) do
|
44
|
+
instance_variable_get(ivar) ||
|
45
|
+
instance_variable_set(ivar, source.find(params[param]))
|
32
46
|
end
|
33
|
-
|
47
|
+
end
|
48
|
+
|
49
|
+
helper_method name, :"#{name}?"
|
50
|
+
protected name, :"#{name}?"
|
34
51
|
end
|
52
|
+
# rubocop:enable CyclomaticComplexity, PerceivedComplexity, AbcSize
|
35
53
|
end
|
36
54
|
end
|
37
55
|
end
|
@@ -41,8 +41,6 @@ module RailsStuff
|
|
41
41
|
def resources_controller(**options)
|
42
42
|
ResourcesController.inject(self, **options)
|
43
43
|
|
44
|
-
respond_to :html
|
45
|
-
self.responder = Responder
|
46
44
|
self.after_save_action = options[:after_save_action] || after_save_action
|
47
45
|
|
48
46
|
resource_belongs_to(*options[:belongs_to]) if options[:belongs_to]
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module RailsStuff
|
2
|
+
module Responders
|
3
|
+
module Turbolinks
|
4
|
+
# Bypasses `:turbolinks` from options.
|
5
|
+
def redirect_to(url, opts = {})
|
6
|
+
if !opts.key?(:turbolinks) && options.key?(:turbolinks)
|
7
|
+
opts[:turbolinks] = options[:turbolinks]
|
8
|
+
end
|
9
|
+
super
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'rails_stuff/responders/turbolinks'
|
2
|
+
|
3
|
+
module RailsStuff
|
4
|
+
# Here are some useful responders extensions.
|
5
|
+
#
|
6
|
+
# Previous versions had responder with SJR helpers, which has been removed.
|
7
|
+
# To achieve same result define responder with:
|
8
|
+
#
|
9
|
+
# class CustomResponder < ActionController::Responder
|
10
|
+
# include Responders::HttpCacheResponder
|
11
|
+
# include RailsStuff::Responders::Turbolinks
|
12
|
+
#
|
13
|
+
# # SJR: render action on failures, redirect on success
|
14
|
+
# alias_method :to_js, :to_html
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
module Responders
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
require 'rails_stuff/test_helpers/concurrency'
|
3
|
+
|
4
|
+
module RailsStuff
|
5
|
+
module RSpecHelpers
|
6
|
+
module Concurrency
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
include RailsStuff::TestHelpers::Concurrency
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
# Defines subject which runs parent's value in multiple threads concurrently.
|
12
|
+
# Define `thread_args` or `threads_count` with `let` to configure it.
|
13
|
+
#
|
14
|
+
# Sets metadata `concurrent: true` so database cleaner uses right strategy.
|
15
|
+
def concurrent_subject!
|
16
|
+
metadata[:concurrent] = true
|
17
|
+
subject do
|
18
|
+
super_proc = super()
|
19
|
+
args = defined?(thread_args) && thread_args
|
20
|
+
args ||= defined?(threads_count) && threads_count
|
21
|
+
-> { concurrently(args, &super_proc) }
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Runs given block in current context and nested context with concurrent subject.
|
26
|
+
#
|
27
|
+
# subject { -> { increment_value_once } }
|
28
|
+
# # This will create 2 examples. One for current contex, and one
|
29
|
+
# # for current context where subject will run multiple times concurrently.
|
30
|
+
# check_concurrent do
|
31
|
+
# it { should change { value }.by(1) }
|
32
|
+
# end
|
33
|
+
def check_concurrent(&block)
|
34
|
+
instance_eval(&block)
|
35
|
+
context 'running multiple times concurrently' do
|
36
|
+
concurrent_subject!
|
37
|
+
instance_eval(&block)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
::RSpec.configuration.include(self) if defined?(::RSpec)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module RailsStuff
|
2
|
+
module RSpecHelpers
|
3
|
+
module Groups
|
4
|
+
module Feature
|
5
|
+
def wait_for_ajax
|
6
|
+
Timeout.timeout(Capybara.default_max_wait_time) do
|
7
|
+
loop until finished_all_ajax_requests?
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
# Tuned for jQuery, override it if you don't use jQuery.
|
12
|
+
def finished_all_ajax_requests?
|
13
|
+
page.evaluate_script('jQuery.active').zero?
|
14
|
+
end
|
15
|
+
|
16
|
+
def pause
|
17
|
+
$stderr.write 'Press enter to continue'
|
18
|
+
$stdin.gets
|
19
|
+
end
|
20
|
+
|
21
|
+
::RSpec.configuration.include self, type: :feature
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
|
3
|
+
module RailsStuff
|
4
|
+
module RSpecHelpers
|
5
|
+
module Groups
|
6
|
+
module Request
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
included do
|
10
|
+
# Define default params for ResourcesController.
|
11
|
+
#
|
12
|
+
# subject { -> { patch(resource_path, params: params) } }
|
13
|
+
# let(:resource) { create(:user) }
|
14
|
+
# let(:resource_params) { {name: 'new name'} }
|
15
|
+
# # params will be {user: {name: 'new name'}}
|
16
|
+
if described_class.respond_to?(:resource_param_name)
|
17
|
+
let(:params) { {described_class.resource_param_name => resource_params} }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
module ClassMethods
|
22
|
+
# Adds `referer`, `referer_path` and `headers` with `let`.
|
23
|
+
# Requires `root_url`
|
24
|
+
def set_referer
|
25
|
+
let(:referer) { root_url.sub(%r{/$}, referer_path) }
|
26
|
+
let(:referer_path) { '/test_referer' }
|
27
|
+
let(:headers) do
|
28
|
+
headers = {Referer: referer}
|
29
|
+
defined?(super) ? super().merge(headers) : headers
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Perform simple request to initialize session.
|
34
|
+
# Useful for `change` matchers.
|
35
|
+
def init_session
|
36
|
+
before do
|
37
|
+
path = defined?(init_session_path) ? init_session_path : '/'
|
38
|
+
get(path)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def with_csrf_protection!
|
43
|
+
around do |ex|
|
44
|
+
begin
|
45
|
+
old = ActionController::Base.allow_forgery_protection
|
46
|
+
ActionController::Base.allow_forgery_protection = true
|
47
|
+
ex.run
|
48
|
+
ensure
|
49
|
+
ActionController::Base.allow_forgery_protection = old
|
50
|
+
end
|
51
|
+
end
|
52
|
+
let(:csrf_response) do
|
53
|
+
path = defined?(csrf_response_path) ? csrf_response_path : '/'
|
54
|
+
get(path) && response.body
|
55
|
+
end
|
56
|
+
let(:csrf_param) { csrf_response.match(/meta name="csrf-param" content="([^"]*)"/)[1] }
|
57
|
+
let(:csrf_token) { csrf_response.match(/<meta name="csrf-token" content="([^"]*)"/)[1] }
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Generate url to current controller.
|
62
|
+
def controller_path(**options)
|
63
|
+
url_for(controller: described_class.controller_path, only_path: true, **options)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Generate url to current controller with resource and default action to `:show`.
|
67
|
+
# It uses `resource` method by default:
|
68
|
+
#
|
69
|
+
# expect(resource_path).to eq resource_path(resource)
|
70
|
+
# resource_path(other_user, action: :edit)
|
71
|
+
def resource_path(resource = self.resource, **options)
|
72
|
+
controller_path(action: :show, id: resource, **options)
|
73
|
+
end
|
74
|
+
|
75
|
+
::RSpec.configuration.include self, type: :request
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
RSpec::Matchers.define :be_valid_js do
|
2
|
+
match_unless_raises do |actual|
|
3
|
+
ExecJS.exec("var test = function(){\n#{actual}\n}")
|
4
|
+
end
|
5
|
+
|
6
|
+
failure_message do |actual|
|
7
|
+
js_error = rescued_exception.message
|
8
|
+
line = js_error.lines[0].split(':').last.to_i - 1
|
9
|
+
js_error = /SyntaxError.*$/.match(js_error)[0] if js_error.include?('SyntaxError')
|
10
|
+
"expected string to be valid js, got '#{js_error}' on line #{line} for\n\n#{actual}"
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module RailsStuff
|
2
|
+
module RSpecHelpers
|
3
|
+
module Matchers
|
4
|
+
module RedirectWithTurbolinks
|
5
|
+
include ::RSpec::Matchers
|
6
|
+
|
7
|
+
class XhrFailure < StandardError; end
|
8
|
+
|
9
|
+
def matches?(response)
|
10
|
+
return unless @scope.request
|
11
|
+
if @scope.request.xhr?
|
12
|
+
match_unless_raises(XhrFailure) { matches_xhr?(response) }
|
13
|
+
else
|
14
|
+
super
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def failure_message
|
19
|
+
@scope.request ? super : 'Request was not performed'
|
20
|
+
end
|
21
|
+
|
22
|
+
def matches_xhr?(response)
|
23
|
+
unless be_ok.matches?(response)
|
24
|
+
raise XhrFailure, "Expect #{response.inspect} to be OK for Turbolinks redirect"
|
25
|
+
end
|
26
|
+
location, _options = turbolinks_location(response)
|
27
|
+
raise XhrFailure, "No Turbolinks redirect in\n\n#{response.body}" unless location
|
28
|
+
active_support_assertion(location)
|
29
|
+
end
|
30
|
+
|
31
|
+
def turbolinks_location(response)
|
32
|
+
body = response.body
|
33
|
+
return unless body
|
34
|
+
match_data = /Turbolinks\.visit\(([^,]+)(,\s*([^)]+))?\)/.match(body)
|
35
|
+
return unless match_data
|
36
|
+
[match_data[1], match_data[3]].map { |x| JSON.parse("[#{x}]")[0] }
|
37
|
+
end
|
38
|
+
|
39
|
+
def active_support_assertion(location)
|
40
|
+
redirect_is = @scope.send(:normalize_argument_to_redirection, location)
|
41
|
+
redirect_expected = @scope.send(:normalize_argument_to_redirection, @expected)
|
42
|
+
message = "Expected response to be a Turbolinks redirect to <#{redirect_expected}>" \
|
43
|
+
" but was a redirect to <#{redirect_is}>"
|
44
|
+
@scope.assert_operator redirect_expected, :===, redirect_is, message
|
45
|
+
rescue ActiveSupport::TestCase::Assertion => e
|
46
|
+
raise XhrFailure, e
|
47
|
+
end
|
48
|
+
|
49
|
+
::RSpec::Rails::Matchers::RedirectTo::RedirectTo.prepend(self) if defined?(::RSpec::Rails)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module RailsStuff
|
2
|
+
module RSpecHelpers
|
3
|
+
module Signinable
|
4
|
+
# Context-level helper to add before filter to sign in user.
|
5
|
+
# Adds `current_user` with let if not defined yet or with gven block.
|
6
|
+
#
|
7
|
+
# Instance-level `sign_in(user_or_nil)` method must be defined, so
|
8
|
+
# this module can be used in any of feature, request or controller groups.
|
9
|
+
#
|
10
|
+
# sign_in { owner }
|
11
|
+
# sign_in # will call current_user or define it with nil
|
12
|
+
def sign_in(&block)
|
13
|
+
if block || !instance_methods.include?(:current_user)
|
14
|
+
block ||= ->(*) {}
|
15
|
+
let(:current_user, &block)
|
16
|
+
end
|
17
|
+
before { sign_in(instance_eval { current_user }) }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|