page_record 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.rubocop.yml +13 -0
- data/CHANGES.md +5 -0
- data/Gemfile.lock +46 -14
- data/Guardfile +24 -0
- data/README.md +27 -1
- data/bin/autospec +16 -0
- data/bin/guard +16 -0
- data/bin/rake +16 -0
- data/bin/rspec +16 -0
- data/lib/page_record/attribute_accessors.rb +57 -54
- data/lib/page_record/base.rb +27 -22
- data/lib/page_record/class_actions.rb +47 -50
- data/lib/page_record/class_methods.rb +252 -261
- data/lib/page_record/errors.rb +81 -82
- data/lib/page_record/finders.rb +129 -131
- data/lib/page_record/form_builder.rb +4 -4
- data/lib/page_record/formtastic.rb +20 -9
- data/lib/page_record/helpers.rb +192 -131
- data/lib/page_record/inspector.rb +36 -0
- data/lib/page_record/instance_actions.rb +44 -46
- data/lib/page_record/rspec.rb +1 -1
- data/lib/page_record/validation.rb +46 -0
- data/lib/page_record/version.rb +1 -1
- data/lib/page_record.rb +13 -15
- data/page_record.gemspec +4 -1
- data/spec/.rubocop.yml +4 -0
- data/spec/helpers_spec.rb +109 -100
- data/spec/inspector_spec.rb +70 -0
- data/spec/page_record_spec.rb +357 -388
- data/spec/spec_helper.rb +1 -3
- data/spec/support/shared_contexts.rb +24 -2
- data/spec/support/shared_examples.rb +41 -45
- data/spec/support/team.rb +4 -4
- data/spec/support/test_app.rb +10 -13
- data/spec/support/views/page-with-1-error.erb +5 -0
- data/spec/support/views/page-with-2-errors-on-different-attributes.erb +9 -0
- data/spec/support/views/page-with-2-errors-on-same-attribute.erb +6 -0
- data/spec/support/views/page-without-errors.erb +4 -0
- data/spec/validation_spec.rb +142 -0
- data/tmp/rspec_guard_result +1 -0
- metadata +80 -5
data/.rubocop.yml
ADDED
data/CHANGES.md
CHANGED
@@ -15,3 +15,8 @@
|
|
15
15
|
##V0.4.0
|
16
16
|
* Added support for Formtasic
|
17
17
|
* Added spec's for rails helpers
|
18
|
+
|
19
|
+
##V0.5.0
|
20
|
+
* Added a rails project containing some cucumber features to demonstrate how it works. The example also shows how to use the rails and Formtastic helpers.
|
21
|
+
* Added support for form validations. Both in formtastic and in reading the errors
|
22
|
+
* added a `inspect` for both the class and for the instances. This is __very__ helpfull when dubugging.
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
page_record (0.
|
4
|
+
page_record (0.5.0)
|
5
|
+
activemodel
|
5
6
|
activesupport
|
6
7
|
capybara (~> 2.1.0)
|
7
8
|
|
@@ -38,6 +39,7 @@ GEM
|
|
38
39
|
rack (>= 1.0.0)
|
39
40
|
rack-test (>= 0.5.4)
|
40
41
|
xpath (~> 2.0)
|
42
|
+
coderay (1.0.9)
|
41
43
|
colorize (0.5.8)
|
42
44
|
coveralls (0.6.7)
|
43
45
|
colorize
|
@@ -47,13 +49,34 @@ GEM
|
|
47
49
|
thor
|
48
50
|
diff-lcs (1.2.4)
|
49
51
|
erubis (2.7.0)
|
52
|
+
ffi (1.9.0)
|
53
|
+
formatador (0.2.4)
|
54
|
+
guard (1.8.1)
|
55
|
+
formatador (>= 0.2.4)
|
56
|
+
listen (>= 1.0.0)
|
57
|
+
lumberjack (>= 1.0.2)
|
58
|
+
pry (>= 0.9.10)
|
59
|
+
thor (>= 0.14.6)
|
60
|
+
guard-rspec (3.0.2)
|
61
|
+
guard (>= 1.8)
|
62
|
+
rspec (~> 2.13)
|
50
63
|
i18n (0.6.4)
|
64
|
+
listen (1.2.2)
|
65
|
+
rb-fsevent (>= 0.9.3)
|
66
|
+
rb-inotify (>= 0.9)
|
67
|
+
rb-kqueue (>= 0.2)
|
68
|
+
lumberjack (1.0.4)
|
69
|
+
method_source (0.8.1)
|
51
70
|
mime-types (1.23)
|
52
|
-
mini_portile (0.5.
|
71
|
+
mini_portile (0.5.1)
|
53
72
|
minitest (4.7.5)
|
54
73
|
multi_json (1.7.7)
|
55
74
|
nokogiri (1.6.0)
|
56
75
|
mini_portile (~> 0.5.0)
|
76
|
+
pry (0.9.12.2)
|
77
|
+
coderay (~> 1.0.5)
|
78
|
+
method_source (~> 0.8)
|
79
|
+
slop (~> 3.4)
|
57
80
|
rack (1.5.2)
|
58
81
|
rack-protection (1.5.0)
|
59
82
|
rack
|
@@ -65,23 +88,29 @@ GEM
|
|
65
88
|
rake (>= 0.8.7)
|
66
89
|
thor (>= 0.18.1, < 2.0)
|
67
90
|
rake (10.1.0)
|
91
|
+
rb-fsevent (0.9.3)
|
92
|
+
rb-inotify (0.9.0)
|
93
|
+
ffi (>= 0.5.0)
|
94
|
+
rb-kqueue (0.2.0)
|
95
|
+
ffi (>= 0.5.0)
|
68
96
|
rest-client (1.6.7)
|
69
97
|
mime-types (>= 1.16)
|
70
|
-
rspec (2.
|
71
|
-
rspec-core (~> 2.
|
72
|
-
rspec-expectations (~> 2.
|
73
|
-
rspec-mocks (~> 2.
|
74
|
-
rspec-core (2.
|
75
|
-
rspec-expectations (2.
|
98
|
+
rspec (2.14.1)
|
99
|
+
rspec-core (~> 2.14.0)
|
100
|
+
rspec-expectations (~> 2.14.0)
|
101
|
+
rspec-mocks (~> 2.14.0)
|
102
|
+
rspec-core (2.14.4)
|
103
|
+
rspec-expectations (2.14.0)
|
76
104
|
diff-lcs (>= 1.1.3, < 2.0)
|
77
|
-
rspec-mocks (2.
|
78
|
-
rspec-rails (2.
|
105
|
+
rspec-mocks (2.14.1)
|
106
|
+
rspec-rails (2.14.0)
|
79
107
|
actionpack (>= 3.0)
|
80
108
|
activesupport (>= 3.0)
|
81
109
|
railties (>= 3.0)
|
82
|
-
rspec-core (~> 2.
|
83
|
-
rspec-expectations (~> 2.
|
84
|
-
rspec-mocks (~> 2.
|
110
|
+
rspec-core (~> 2.14.0)
|
111
|
+
rspec-expectations (~> 2.14.0)
|
112
|
+
rspec-mocks (~> 2.14.0)
|
113
|
+
ruby_gntp (0.3.4)
|
85
114
|
simplecov (0.7.1)
|
86
115
|
multi_json (~> 1.0)
|
87
116
|
simplecov-html (~> 0.7.1)
|
@@ -90,8 +119,9 @@ GEM
|
|
90
119
|
rack (~> 1.4)
|
91
120
|
rack-protection (~> 1.4)
|
92
121
|
tilt (~> 1.3, >= 1.3.4)
|
122
|
+
slop (3.4.6)
|
93
123
|
thor (0.18.1)
|
94
|
-
thread_safe (0.1.
|
124
|
+
thread_safe (0.1.2)
|
95
125
|
atomic
|
96
126
|
tilt (1.4.1)
|
97
127
|
tzinfo (0.3.37)
|
@@ -106,8 +136,10 @@ DEPENDENCIES
|
|
106
136
|
activerecord
|
107
137
|
bundler (~> 1.3)
|
108
138
|
coveralls
|
139
|
+
guard-rspec
|
109
140
|
page_record!
|
110
141
|
rake
|
111
142
|
rspec
|
112
143
|
rspec-rails
|
144
|
+
ruby_gntp
|
113
145
|
sinatra
|
data/Guardfile
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# A sample Guardfile
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
3
|
+
|
4
|
+
guard 'rspec' do
|
5
|
+
watch(%r{^spec/.+_spec\.rb$})
|
6
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
7
|
+
watch('spec/spec_helper.rb') { "spec" }
|
8
|
+
|
9
|
+
# Rails example
|
10
|
+
watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
11
|
+
watch(%r{^app/(.*)(\.erb|\.haml)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
|
12
|
+
watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
|
13
|
+
watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
|
14
|
+
watch('config/routes.rb') { "spec/routing" }
|
15
|
+
watch('app/controllers/application_controller.rb') { "spec/controllers" }
|
16
|
+
|
17
|
+
# Capybara features specs
|
18
|
+
watch(%r{^app/views/(.+)/.*\.(erb|haml)$}) { |m| "spec/features/#{m[1]}_spec.rb" }
|
19
|
+
|
20
|
+
# Turnip features and steps
|
21
|
+
watch(%r{^spec/acceptance/(.+)\.feature$})
|
22
|
+
watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
|
23
|
+
end
|
24
|
+
|
data/README.md
CHANGED
@@ -7,7 +7,33 @@ You've probably been there. You're building your killer Web Application. You, be
|
|
7
7
|
## PageRecord can help.
|
8
8
|
There are a lot of ways you can do this. PageRecord is one of these ways. PageRecord is an ActiveRecord like abstraction for information on the HTML page. You can use `TeamRecord.find(1)` and `TeamRecord.find_by_name('Barcelona')` like functions to find a record on an HTML page. When you've found the record you need, you can use easy accessors to access the attributes. `TeamRecord.find(1).name` returns the name of the team.
|
9
9
|
|
10
|
-
|
10
|
+
###Adding a record using a form
|
11
|
+
|
12
|
+
With the PageRecord api you can fill all form fields press the save button.
|
13
|
+
|
14
|
+
```ruby
|
15
|
+
When(/^I add a team$/) do
|
16
|
+
visit new_team_path
|
17
|
+
team = TeamPage.find
|
18
|
+
team.name = "Ajax"
|
19
|
+
team.competition = @competition
|
20
|
+
team.save
|
21
|
+
end
|
22
|
+
```
|
23
|
+
|
24
|
+
###Checking if an error is displayed.
|
25
|
+
|
26
|
+
With the PageRecord api you can check for errors. No need to checkout what css you need to select the right DOM element. PageRecord takes care of that.
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
Then(/^I should see error "can't be blank" on field "competition"$/) do
|
30
|
+
team = TeamPage.find
|
31
|
+
expect(team.errors['competition']).to eq ['can't be blank']
|
32
|
+
end
|
33
|
+
```
|
34
|
+
|
35
|
+
###How to get the right HTML?
|
36
|
+
PageRecord contains form builders that make it extremely easy to build the right forms. When you use Formtastic. You don't have to do anything. PageRecord add's the right attributes to the right DOM elements. When you use barebone Rails, you van use the `record_form_for` form builder. See the example for more information.
|
11
37
|
|
12
38
|
##Documentation
|
13
39
|
Look at [the yard documentation](http://rubydoc.info/github/appdrones/page_record/PageRecord) for details. Check [Changes](https://github.com/appdrones/page_record/blob/master/CHANGES.md) for (breaking) changes per version.
|
data/bin/autospec
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# This file was generated by Bundler.
|
4
|
+
#
|
5
|
+
# The application 'autospec' is installed as part of a gem, and
|
6
|
+
# this file is here to facilitate running it.
|
7
|
+
#
|
8
|
+
|
9
|
+
require 'pathname'
|
10
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
11
|
+
Pathname.new(__FILE__).realpath)
|
12
|
+
|
13
|
+
require 'rubygems'
|
14
|
+
require 'bundler/setup'
|
15
|
+
|
16
|
+
load Gem.bin_path('rspec-core', 'autospec')
|
data/bin/guard
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# This file was generated by Bundler.
|
4
|
+
#
|
5
|
+
# The application 'guard' is installed as part of a gem, and
|
6
|
+
# this file is here to facilitate running it.
|
7
|
+
#
|
8
|
+
|
9
|
+
require 'pathname'
|
10
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
11
|
+
Pathname.new(__FILE__).realpath)
|
12
|
+
|
13
|
+
require 'rubygems'
|
14
|
+
require 'bundler/setup'
|
15
|
+
|
16
|
+
load Gem.bin_path('guard', 'guard')
|
data/bin/rake
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# This file was generated by Bundler.
|
4
|
+
#
|
5
|
+
# The application 'rake' is installed as part of a gem, and
|
6
|
+
# this file is here to facilitate running it.
|
7
|
+
#
|
8
|
+
|
9
|
+
require 'pathname'
|
10
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
11
|
+
Pathname.new(__FILE__).realpath)
|
12
|
+
|
13
|
+
require 'rubygems'
|
14
|
+
require 'bundler/setup'
|
15
|
+
|
16
|
+
load Gem.bin_path('rake', 'rake')
|
data/bin/rspec
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# This file was generated by Bundler.
|
4
|
+
#
|
5
|
+
# The application 'rspec' is installed as part of a gem, and
|
6
|
+
# this file is here to facilitate running it.
|
7
|
+
#
|
8
|
+
|
9
|
+
require 'pathname'
|
10
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
11
|
+
Pathname.new(__FILE__).realpath)
|
12
|
+
|
13
|
+
require 'rubygems'
|
14
|
+
require 'bundler/setup'
|
15
|
+
|
16
|
+
load Gem.bin_path('rspec-core', 'rspec')
|
@@ -1,60 +1,63 @@
|
|
1
1
|
module PageRecord
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
end
|
2
|
+
class Base
|
3
|
+
##
|
4
|
+
# Searches the record for the specified attribute and returns
|
5
|
+
# the {http://rubydoc.info/github/jnicklas/capybara/master/Capybara/Result Capybara Result}.
|
6
|
+
# This method is called when you access an attribute with a `?` of a record
|
7
|
+
#
|
8
|
+
# @return [Capybara::Result] the text content of the specified attribute
|
9
|
+
#
|
10
|
+
# @raise [AttributeNotFound] when the attribute is not found in the record
|
11
|
+
#
|
12
|
+
def read_attribute?(attribute)
|
13
|
+
@record.find("[data-attribute-for='#{attribute}']")
|
14
|
+
rescue Capybara::ElementNotFound
|
15
|
+
raise AttributeNotFound, "#{@type} record with id #{@id} doesn't contain attribute #{attribute}"
|
16
|
+
end
|
18
17
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
18
|
+
##
|
19
|
+
# Searches the record for the specified attribute and returns
|
20
|
+
# the text content. This method is called when you access an
|
21
|
+
# attribute of a record
|
22
|
+
#
|
23
|
+
# @return [String] the text content of the specified attribute
|
24
|
+
#
|
25
|
+
# @raise [AttributeNotFound] when the attribute is not found in the record
|
26
|
+
#
|
27
|
+
def read_attribute(attribute)
|
28
|
+
element = send("#{attribute}?")
|
29
|
+
tag = element.tag_name
|
30
|
+
input_field?(tag) ? element.value : element.text
|
31
|
+
end
|
32
32
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
33
|
+
##
|
34
|
+
# Searches the record for the specified attribute and sets the value of the attribute
|
35
|
+
# This method is called when you set an attribute of a record
|
36
|
+
#
|
37
|
+
# @return [Capybara::Result] the text content of the specified attribute
|
38
|
+
#
|
39
|
+
# @raise [AttributeNotFound] when the attribute is not found in the record
|
40
|
+
# @raise [NotInputField] when the attribute is not a `TEXTAREA` or `INPUT` tag
|
41
|
+
#
|
42
|
+
def write_attribute(attribute, value)
|
43
|
+
element = send("#{attribute}?")
|
44
|
+
tag = element.tag_name
|
45
|
+
case tag
|
46
|
+
when 'textarea', 'input' then element.set(value)
|
47
|
+
when 'select'then element.select(value)
|
48
|
+
else raise NotInputField
|
49
|
+
end
|
50
|
+
element
|
51
|
+
end
|
49
52
|
|
53
|
+
private
|
50
54
|
|
51
|
-
private
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
end
|
55
|
+
# @private
|
56
|
+
def input_field?(tag)
|
57
|
+
case tag
|
58
|
+
when 'textarea', 'input', 'select' then true
|
59
|
+
else false
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
60
63
|
end
|
data/lib/page_record/base.rb
CHANGED
@@ -1,29 +1,34 @@
|
|
1
1
|
module PageRecord
|
2
2
|
|
3
|
-
|
3
|
+
class Base
|
4
|
+
include PageRecord::Inspector
|
4
5
|
|
5
|
-
|
6
|
-
|
6
|
+
attr_reader :id
|
7
|
+
alias_method :id?, :id
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
9
|
+
def initialize(id = nil, selector = nil, filter = nil)
|
10
|
+
@page = self.class.page
|
11
|
+
@type = self.class.instance_variable_get('@type')
|
12
|
+
@id = id.to_s
|
13
|
+
find_record(selector, filter)
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def find_record(selector, filter)
|
19
|
+
selector ||= @selector
|
20
|
+
filter ||= @filter
|
21
|
+
id_text = @id.blank? ? '' : "='#{@id}'"
|
22
|
+
begin
|
23
|
+
context = self.class.context_for_selector(selector)
|
24
|
+
@record = context.find("[data-#{@type}-id#{id_text}]#{filter}")
|
25
|
+
@id = @record["data-#{@type}-id"] if @id.blank?
|
26
|
+
rescue Capybara::Ambiguous
|
27
|
+
raise MultipleRecords, "Found multiple #{@type} record with id #{@id} on page"
|
28
|
+
rescue Capybara::ElementNotFound
|
29
|
+
raise RecordNotFound, "#{@type} record with id #{@id} not found on page"
|
30
|
+
end
|
31
|
+
end
|
26
32
|
|
27
33
|
end
|
28
34
|
end
|
29
|
-
|
@@ -1,55 +1,52 @@
|
|
1
1
|
module PageRecord
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
2
|
+
class Base
|
3
|
+
##
|
4
|
+
#
|
5
|
+
# This is the implementation of the page action routine. It has two variants.
|
6
|
+
# it has a `?` variant and a `normal` variant.
|
7
|
+
#
|
8
|
+
# normal variant:
|
9
|
+
# It checks the page for a data-action-for='action' tag somewhere on the page.
|
10
|
+
# If it finds it, it clicks it.
|
11
|
+
#
|
12
|
+
# `?` variant:
|
13
|
+
# It checks the page for a data-action-for='action' tag somewhere on the page.
|
14
|
+
# If it finds it, returns the Capybara result.
|
15
|
+
#
|
16
|
+
# @param action [Symbol] this is the name of the action
|
17
|
+
#
|
18
|
+
# @return [Capybara::Element]
|
19
|
+
#
|
20
|
+
# @raise [PageRecord::MultipleRecords] when there are more actions with
|
21
|
+
# this name on the page
|
22
|
+
#
|
23
|
+
def self.method_missing(action)
|
24
|
+
raw_action = /(.*)\?/.match(action)
|
25
|
+
begin
|
26
|
+
if raw_action
|
27
|
+
action_for?(raw_action[1])
|
28
|
+
else
|
29
|
+
action_for(action)
|
30
|
+
end
|
31
|
+
rescue Capybara::Ambiguous
|
32
|
+
raise MultipleRecords, "Found multiple #{action} tags for #{@type} on page"
|
33
|
+
rescue Capybara::ElementNotFound
|
34
|
+
super
|
35
|
+
end
|
36
|
+
end
|
37
37
|
|
38
|
-
private
|
38
|
+
private
|
39
39
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
40
|
+
# @private
|
41
|
+
def self.action_for(action)
|
42
|
+
element = action_for?(action)
|
43
|
+
element.click
|
44
|
+
element
|
45
|
+
end
|
46
46
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
end
|
47
|
+
# @private
|
48
|
+
def self.action_for?(action)
|
49
|
+
page.find("[data-action-for='#{action}']")
|
50
|
+
end
|
51
|
+
end
|
53
52
|
end
|
54
|
-
|
55
|
-
|