seleniumrecord 0.0.1.beta1 → 0.0.2.revision
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.pryrc +6 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +10 -0
- data/README.md +42 -6
- data/lib/generators/selenium_record/install_generator.rb +82 -0
- data/lib/generators/selenium_record/templates/autoload.rb.erb +20 -0
- data/lib/generators/selenium_record/templates/base/application_navigation_component.rb.erb +18 -0
- data/lib/generators/selenium_record/templates/base/application_page.rb.erb +18 -0
- data/lib/generators/selenium_record/templates/base/application_view.rb.erb +7 -0
- data/lib/generators/selenium_record/templates/selenium_record.rb.erb +1 -0
- data/lib/selenium_record/actions.rb +13 -0
- data/lib/selenium_record/axiable.rb +10 -0
- data/lib/selenium_record/base.rb +6 -0
- data/lib/selenium_record/component_autoload.rb +161 -0
- data/lib/selenium_record/configuration.rb +11 -2
- data/lib/selenium_record/core.rb +31 -3
- data/lib/selenium_record/version.rb +1 -1
- data/selenium_record.gemspec +9 -5
- metadata +68 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 73caf7b7709b8398dd7357ea6fdf1f54177faa80
|
4
|
+
data.tar.gz: 1bef8079874943607dbc961b129e0932ffe334bb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0f7251222b5b6976272c802a630df7412bff8890adbd7dc77b7eda6a53eb89c24090586db94dabd7925d6b5f852b504278e5eec0b33aa1f5b625d8f76b761254
|
7
|
+
data.tar.gz: c62ce4b61fae60b831bb3c94994a7c25e85a86be2ff47f1234bff9fb0e709388434e20f78bf0622394d7611e5d05ffa2dcb8509b977f77b098f3a651a85f02b0
|
data/.pryrc
ADDED
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
seleniumrecord
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.1.2
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
## 0.0.2
|
2
|
+
|
3
|
+
* Added rake task for scaffolding
|
4
|
+
* Added documentation for rake task
|
5
|
+
* Added `ComponentAutoload` module
|
6
|
+
* Added `cover` method in `SeleniumRecord::Actions` module for managing
|
7
|
+
`Selenium::WebDriver::Error::StaleElementReferenceError` when clicking
|
8
|
+
elements
|
9
|
+
* Added `Axiable` module to extend `Selenium::WebDriver::Element` when we call
|
10
|
+
to `find` or `find_elements` methods
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
[](http://badge.fury.io/rb/seleniumrecord)
|
2
2
|
[](https://codeclimate.com/github/dsaenztagarro/selenium-record)
|
3
3
|
|
4
4
|
# SeleniumRecord
|
@@ -14,6 +14,42 @@ Selenium Record object simply models these as objects within the test code.
|
|
14
14
|
This reduces the amount of duplicated code and means that if the UI changes,
|
15
15
|
the fix need only be applied in one place.
|
16
16
|
|
17
|
+
## Rake tasks
|
18
|
+
|
19
|
+
**selenium_record:install**
|
20
|
+
|
21
|
+
Generates scaffolding for selenium objects
|
22
|
+
|
23
|
+
```shell
|
24
|
+
bundle exec rake selenium_record:install --test_framework=rspec
|
25
|
+
```
|
26
|
+
|
27
|
+
Options:
|
28
|
+
- 'test_framework': [String] Test framework to use. Possible values: 'rspec',
|
29
|
+
'cucumber', 'test_unit'.
|
30
|
+
- 'object_module': [String] Base module for selenium objects.
|
31
|
+
Default: 'SeleniumObject'
|
32
|
+
- 'navigation_components': [Array] The names of the navigation components
|
33
|
+
expected. Default: ['pages', 'tab']
|
34
|
+
|
35
|
+
## Install
|
36
|
+
|
37
|
+
After running `rake selenium_record::install`, you should include a module in
|
38
|
+
Rspec with:
|
39
|
+
|
40
|
+
```ruby
|
41
|
+
module SeleniumRecordHelpers
|
42
|
+
def browser
|
43
|
+
@browser ||= page.driver.browser
|
44
|
+
end
|
45
|
+
|
46
|
+
def create_page(page_sym)
|
47
|
+
klass = page_sym.to_s.camelize
|
48
|
+
"SeleniumObjects::Pages::#{klass}Page".constantize.new(browser).load_dom!
|
49
|
+
end
|
50
|
+
end
|
51
|
+
```
|
52
|
+
|
17
53
|
## Warning
|
18
54
|
|
19
55
|
This gem is still under development! As this gem was born while I was trying to
|
@@ -23,10 +59,10 @@ should be completed for '1.0.0' version. Keep up to date!
|
|
23
59
|
|
24
60
|
## Roadmap
|
25
61
|
|
26
|
-
[ ] Full test coverage
|
27
|
-
[ ] Wiki Documentation
|
28
|
-
[
|
29
|
-
[
|
62
|
+
- [ ] Full test coverage
|
63
|
+
- [ ] Wiki and README Documentation
|
64
|
+
- [X] Basic install generator
|
65
|
+
- [X] ComponentAutoload integration in core (Currently present as a framework
|
30
66
|
extension)
|
31
67
|
|
32
68
|
## Installation
|
@@ -62,4 +98,4 @@ TODO: Write usage instructions here
|
|
62
98
|
|
63
99
|
## Thanks
|
64
100
|
|
65
|
-
Thanks to Hola Internet for let me right this kind of tools
|
101
|
+
Thanks to [Hola Internet](https://github.com/holadev) for let me right this kind of tools
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'active_support/inflector'
|
2
|
+
require 'pry'
|
3
|
+
|
4
|
+
module SeleniumRecord
|
5
|
+
module Generators
|
6
|
+
# Generator for installing selenium record in project
|
7
|
+
class InstallGenerator < Rails::Generators::Base
|
8
|
+
desc 'Copy SeleniumRecord default files'
|
9
|
+
source_root File.expand_path('../templates', __FILE__)
|
10
|
+
class_option :objects_module, type: :string, default: 'SeleniumObjects',
|
11
|
+
desc: 'Module containing selenium objects'
|
12
|
+
class_option :test_framework, type: :string, default: 'rspec',
|
13
|
+
desc: 'Test framework used'
|
14
|
+
class_option :navigation_components, type: :array,
|
15
|
+
default: %w(page tab),
|
16
|
+
desc: 'Navigation components'
|
17
|
+
|
18
|
+
# def create_initializer_file
|
19
|
+
# template 'selenium_record.rb.erb',
|
20
|
+
# 'config/initializers/selenium_record.rb'
|
21
|
+
# end
|
22
|
+
|
23
|
+
def create_base_dir
|
24
|
+
empty_directory object_module_path
|
25
|
+
end
|
26
|
+
|
27
|
+
def create_common_components
|
28
|
+
%w(page view).each { |c| create_component(c) }
|
29
|
+
end
|
30
|
+
|
31
|
+
def create_navigation_components
|
32
|
+
options[:navigation_components].each { |c| create_component(c) }
|
33
|
+
end
|
34
|
+
|
35
|
+
def create_autoload
|
36
|
+
@navigation_components = options[:navigation_components]
|
37
|
+
@navigation_folders = @navigation_components.map do |component|
|
38
|
+
ActiveSupport::Inflector.pluralize(component)
|
39
|
+
end.join(' ')
|
40
|
+
template 'autoload.rb.erb', File.join(object_module_path, 'autoload.rb')
|
41
|
+
end
|
42
|
+
|
43
|
+
def add_includes_spec_helper
|
44
|
+
prepend_to_file 'spec/spec_helper.rb' do
|
45
|
+
"# SeleniumRecord install configuration\n" \
|
46
|
+
"require 'selenium-webdriver'\n" \
|
47
|
+
"require 'selenium_record'\n" \
|
48
|
+
"require_relative 'support/selenium_objects/base'\n\n"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def create_component(component)
|
55
|
+
om_path = object_module_path
|
56
|
+
comp_folder = ActiveSupport::Inflector.pluralize(component)
|
57
|
+
empty_directory File.join om_path, comp_folder
|
58
|
+
@component_klass = ActiveSupport::Inflector.classify(component)
|
59
|
+
template 'base/application_navigation_component.rb.erb',
|
60
|
+
File.join(om_path, 'base', "application_#{component}.rb")
|
61
|
+
end
|
62
|
+
|
63
|
+
def object_module_folder
|
64
|
+
om_name = options[:objects_module].to_s
|
65
|
+
ActiveSupport::Inflector.underscore(om_name)
|
66
|
+
end
|
67
|
+
|
68
|
+
def object_module_path
|
69
|
+
File.join destination_root, test_folder, 'support', object_module_folder
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_folder
|
73
|
+
case options[:test_framework]
|
74
|
+
when 'rspec' then 'spec'
|
75
|
+
when 'cucumber' then 'features'
|
76
|
+
else
|
77
|
+
'test'
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module SeleniumObjects
|
2
|
+
# Base classes for all selenium objects
|
3
|
+
module Base
|
4
|
+
# Navigation components
|
5
|
+
<% @navigation_components.each do |component| %>
|
6
|
+
require_relative "base/application_<%= component %>"
|
7
|
+
<% end %>
|
8
|
+
# Base components
|
9
|
+
require_relative 'base/application_view'
|
10
|
+
require_relative 'base/application_page'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
%w(<%= @navigation_folders %> views pages).each do |folder|
|
15
|
+
Dir["#{File.dirname(__FILE__)}/#{folder}/*.rb"].each { |f| require f }
|
16
|
+
end
|
17
|
+
|
18
|
+
RSpec.configure do |config|
|
19
|
+
config.include SeleniumObjects::Pages, type: :feature # js: true
|
20
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module SeleniumObjects
|
2
|
+
module Base
|
3
|
+
# Base class for all selenium objects representing an application page
|
4
|
+
class Application<%= @component_klass %> < ::SeleniumRecord::NavigationItem
|
5
|
+
private
|
6
|
+
|
7
|
+
# @return [String] the locator for the inactive menu of the page
|
8
|
+
def link_inactive_locator
|
9
|
+
# Replace with: { locatorType: argument }
|
10
|
+
end
|
11
|
+
|
12
|
+
# @return [String] the locator for the active menu link of the page
|
13
|
+
def link_active_locator
|
14
|
+
# Replace with: { locatorType: argument }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module SeleniumObjects
|
2
|
+
module Base
|
3
|
+
# Base class for all selenium objects representing an application page
|
4
|
+
class ApplicationPage < ::SeleniumRecord::NavigationItem
|
5
|
+
private
|
6
|
+
|
7
|
+
# @return [String] the locator for the inactive menu of the page
|
8
|
+
def link_inactive_locator
|
9
|
+
# Replace with: { locatorType: argument }
|
10
|
+
end
|
11
|
+
|
12
|
+
# @return [String] the locator for the active menu link of the page
|
13
|
+
def link_active_locator
|
14
|
+
# Replace with: { locatorType: argument }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
SeleniumRecord.objects_module = <%= options[:objects_module] %>
|
@@ -28,6 +28,13 @@ module SeleniumRecord
|
|
28
28
|
click_wait xpath: dropdown_menu_xpath(trans menu)
|
29
29
|
end
|
30
30
|
|
31
|
+
# Clear input of type 'text'
|
32
|
+
def clear(locator)
|
33
|
+
el = find(locator)
|
34
|
+
el.send_keys('')
|
35
|
+
el.clear
|
36
|
+
end
|
37
|
+
|
31
38
|
# Clicks on element and wait until all jquery events are dispatched
|
32
39
|
# @param how [Symbol] (:class, :class_name, :css, :id, :link_text, :link,
|
33
40
|
# :partial_link_text, :name, :tag_name, :xpath)
|
@@ -41,6 +48,12 @@ module SeleniumRecord
|
|
41
48
|
find(locator).click
|
42
49
|
end
|
43
50
|
|
51
|
+
def fill(locator, text)
|
52
|
+
return unless text
|
53
|
+
clear(locator)
|
54
|
+
find(locator).send_keys(text || '')
|
55
|
+
end
|
56
|
+
|
44
57
|
def submit
|
45
58
|
click(xpath: ".//button[@type='submit']")
|
46
59
|
wait_page_load
|
@@ -0,0 +1,10 @@
|
|
1
|
+
module SeleniumRecord
|
2
|
+
# Xpath axes helper methods for extending Selenium::WebDriver::Element
|
3
|
+
module Axiable
|
4
|
+
# @param element [Selenium::WebDriver::Element]
|
5
|
+
# @return [Selenium::WebDriver::Element] The preceding-sibling axis element
|
6
|
+
def preceding_sibling(tag_name)
|
7
|
+
find_element xpath: "./preceding-sibling::#{tag_name}"
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
data/lib/selenium_record/base.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require_relative 'configuration'
|
1
2
|
require_relative 'core'
|
2
3
|
require_relative 'lookup'
|
3
4
|
require_relative 'actions'
|
@@ -9,6 +10,9 @@ require_relative 'axis'
|
|
9
10
|
require_relative 'html'
|
10
11
|
require_relative 'theme'
|
11
12
|
require_relative 'translations'
|
13
|
+
require_relative 'component_autoload'
|
14
|
+
|
15
|
+
require 'active_support/inflector'
|
12
16
|
|
13
17
|
# SeleniumRecord provides a framework based on the Selenium Page Object pattern
|
14
18
|
#
|
@@ -19,6 +23,7 @@ module SeleniumRecord
|
|
19
23
|
# @abstract Subclass and override {#run} to implement
|
20
24
|
# a custom Selenium object
|
21
25
|
class Base
|
26
|
+
include Configuration
|
22
27
|
include Core
|
23
28
|
include Lookup
|
24
29
|
include Actions
|
@@ -30,6 +35,7 @@ module SeleniumRecord
|
|
30
35
|
include Html
|
31
36
|
include Theme
|
32
37
|
include Translations
|
38
|
+
include ComponentAutoload
|
33
39
|
attr_reader :browser, :parent_el, :root_el, :object
|
34
40
|
alias_method :__rootel__, :root_el
|
35
41
|
|
@@ -0,0 +1,161 @@
|
|
1
|
+
module SeleniumRecord
|
2
|
+
# Provides shortcuts for selenium object creation
|
3
|
+
module ComponentAutoload
|
4
|
+
# Error raised when it is not found the component
|
5
|
+
class UnknownComponent < StandardError
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.included(base)
|
9
|
+
base.extend(ClassMethods)
|
10
|
+
base.instance_eval do
|
11
|
+
attr_reader :components
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# @param modules [Array<String>]
|
16
|
+
# @return [Module] the module containing the classes for the marker type
|
17
|
+
# group
|
18
|
+
def self.extract_namespace(*modules)
|
19
|
+
modules.compact.reduce(Configuration.objects_module) do |klass, sym|
|
20
|
+
klass.const_get(sym)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# @param suffixes [Array<String>]
|
25
|
+
def self.extract_group(klass_name, opts = {})
|
26
|
+
return unless opts[:nested_folder]
|
27
|
+
suffixes = [*opts[:suffixes]]
|
28
|
+
suffixes.map do |suffix|
|
29
|
+
match_data = Regexp.new("^(.*)#{suffix}$").match(klass_name)
|
30
|
+
match_data[1] if match_data
|
31
|
+
end.compact.first
|
32
|
+
end
|
33
|
+
|
34
|
+
# @param component_type [Symbol]
|
35
|
+
# @param item [Symbol]
|
36
|
+
# @param klass [SeleniumRecord::Base]
|
37
|
+
# @param suffixes [Array<String>]
|
38
|
+
def self.extract_options(component_type, klass, opts = {})
|
39
|
+
suffix = component_type.to_s.capitalize
|
40
|
+
group = extract_group(klass.name.split('::').last, opts)
|
41
|
+
namespace = extract_namespace(suffix.pluralize, group)
|
42
|
+
{ namespace: namespace, suffix: suffix, subject: opts[:subject] }
|
43
|
+
end
|
44
|
+
|
45
|
+
# @param component_type [Symbol] type of component
|
46
|
+
# @param _ [String] the return type to show in autogenerated documentation
|
47
|
+
# @param [Hash] opts the options of component loader
|
48
|
+
# @param opts [Array<String>] suffixes The list of valid suffixes for
|
49
|
+
# parent classes of the instantiated component
|
50
|
+
# @option opts [String] :nested_folder Marks whether to search the
|
51
|
+
# component inside a folder specific to parent component
|
52
|
+
def self.component_loader(component_type, _, opts = {})
|
53
|
+
mod = self
|
54
|
+
define_method "#{component_type}_for" do |item|
|
55
|
+
record_opts = mod.extract_options(component_type, self.class, {
|
56
|
+
subject: item.to_s.camelize,
|
57
|
+
suffixes: %w(View)
|
58
|
+
}.merge(opts))
|
59
|
+
create_record(object, record_opts).tap(&:load_dom)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# @macro [attach] component
|
64
|
+
# @method $1_for($1_sym)
|
65
|
+
# @param $1_sym [Symbol]
|
66
|
+
# @return [$2]
|
67
|
+
component_loader :panel, 'SeleniumRecord::Base', nested_folder: true,
|
68
|
+
suffixes: %w(Pill)
|
69
|
+
component_loader :tab, 'SeleniumObjects::Tabs::ApplicationTab',
|
70
|
+
nested_folder: true
|
71
|
+
component_loader :pill, 'SeleniumObjects::Pills::ApplicationPill',
|
72
|
+
nested_folder: true, suffixes: %w(Tab)
|
73
|
+
component_loader :modal, 'SeleniumRecord::Base'
|
74
|
+
|
75
|
+
# @param model [ActiveRecord::Base]
|
76
|
+
# @param [Hash] opts the options to instance a view
|
77
|
+
# @param opts [String] :subject The name of the view. Default to model class
|
78
|
+
# name
|
79
|
+
# @return [SeleniumObject::View::ApplicationView]
|
80
|
+
def view_for(model, opts = {})
|
81
|
+
view_options = opts.merge namespace: so_module(:views), suffix: 'View'
|
82
|
+
create_record(model, view_options).tap(&:load_dom)
|
83
|
+
end
|
84
|
+
|
85
|
+
# Proxies all calls to component methods
|
86
|
+
def method_missing(method, *args)
|
87
|
+
[*@components].each do |comp|
|
88
|
+
return comp.send(method, *args) if comp.respond_to?(method)
|
89
|
+
end
|
90
|
+
rescue UnknownComponent
|
91
|
+
super
|
92
|
+
end
|
93
|
+
|
94
|
+
# Class method helpers for autoloading components
|
95
|
+
module ClassMethods
|
96
|
+
def component_method_regex
|
97
|
+
/(?<component_name>.*)_(?<component_type>view|tab|pill|modal|panel)$/
|
98
|
+
end
|
99
|
+
|
100
|
+
# Inject components after loading dom, providing reader methods for
|
101
|
+
# accessing them
|
102
|
+
# @param names [Array<Symbol>] component names. Valid formats Regex:
|
103
|
+
# /(?<component_name>.*)_(?<component_type>view|tab|pill|modal|panel)$/
|
104
|
+
def component_reader(*names)
|
105
|
+
names.each { |name| create_component_reader name }
|
106
|
+
define_method :after_load_dom do
|
107
|
+
load_components names
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def action_component_reader(*names)
|
112
|
+
names.each { |name| load_action_component name }
|
113
|
+
end
|
114
|
+
|
115
|
+
private
|
116
|
+
|
117
|
+
def create_component_reader(name)
|
118
|
+
define_method name do
|
119
|
+
instance_variable_get "@#{name}"
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
# @param name [Symbol] name of the component. Valid formats Regex:
|
124
|
+
# /(?<component_name>.*)_(?<component_type>tab|pill|modal)$/
|
125
|
+
def load_action_component(name)
|
126
|
+
define_method name do
|
127
|
+
component_for name
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
private
|
133
|
+
|
134
|
+
# @param names [Array<Symbol>] list of names of the components.
|
135
|
+
# Valid formats Regex:
|
136
|
+
# /(?<component_name>.*)_(?<component_type>view|tab|pill|modal|panel)$/
|
137
|
+
def load_components(names)
|
138
|
+
@components ||= []
|
139
|
+
names.each { |name| load_component name }
|
140
|
+
end
|
141
|
+
|
142
|
+
# @param name [Symbol] name of the component. Valid formats Regex:
|
143
|
+
# /(?<component_name>.*)_(?<component_type>view|panel)$/
|
144
|
+
def load_component(name)
|
145
|
+
component = component_for name
|
146
|
+
instance_variable_set("@#{name}", component)
|
147
|
+
@components << component
|
148
|
+
end
|
149
|
+
|
150
|
+
# @param name [Symbol] name of the component. Valid formats Regex:
|
151
|
+
# /(?<component_name>.*)_(?<component_type>view|tab|pill|modal|panel)$/
|
152
|
+
def component_for(name)
|
153
|
+
matches = self.class.component_method_regex.match(name)
|
154
|
+
if matches
|
155
|
+
send "#{matches[:component_type]}_for", matches[:component_name]
|
156
|
+
else
|
157
|
+
fail UnknownComponent
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
@@ -1,11 +1,20 @@
|
|
1
1
|
module SeleniumRecord
|
2
2
|
# Defines configuration options
|
3
|
-
|
3
|
+
module Configuration
|
4
4
|
@js_library = :jquery
|
5
5
|
@choose_option_max_retries = 10
|
6
6
|
|
7
7
|
class << self
|
8
|
-
attr_accessor :js_library, :choose_option_max_retries
|
8
|
+
attr_accessor :js_library, :choose_option_max_retries, :objects_module
|
9
|
+
end
|
10
|
+
|
11
|
+
# param object_type [Symbol] The object type
|
12
|
+
# @return [Module] The module containing classes of object type
|
13
|
+
def so_module(object_type = nil)
|
14
|
+
base_module = SeleniumRecord::Configuration.objects_module
|
15
|
+
return base_module unless object_type
|
16
|
+
klass = object_type.to_s.classify.pluralize
|
17
|
+
base_module.const_get(klass)
|
9
18
|
end
|
10
19
|
end
|
11
20
|
end
|
data/lib/selenium_record/core.rb
CHANGED
@@ -22,17 +22,45 @@ module SeleniumRecord
|
|
22
22
|
find(locator).click
|
23
23
|
end
|
24
24
|
|
25
|
-
|
26
|
-
|
25
|
+
# @param [Hash] opts the options to find element
|
26
|
+
# @param opts [String] :global_scope Marks whether the global scope is used
|
27
|
+
# whenever a root element is not present
|
28
|
+
# @return [Selenium::WebDriver::Element]
|
29
|
+
def find(locator, opts = {})
|
30
|
+
cover do
|
31
|
+
finder = root_el
|
32
|
+
finder = browser if opts[:global_scope] && !finder
|
33
|
+
element = finder.find_element(locator)
|
34
|
+
element.extend(Axiable)
|
35
|
+
element
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def find!(locator)
|
40
|
+
find(locator, global_scope: true)
|
27
41
|
end
|
28
42
|
|
29
43
|
def find_elements(locator)
|
30
|
-
root_el.find_elements(locator)
|
44
|
+
cover { root_el.find_elements(locator) }
|
31
45
|
end
|
32
46
|
|
33
47
|
def first_last(list)
|
34
48
|
blk = ->(first, *_, last) { [first, last] }
|
35
49
|
blk.call(*list)
|
36
50
|
end
|
51
|
+
|
52
|
+
protected
|
53
|
+
|
54
|
+
# Runs block code free of:
|
55
|
+
# `Selenium::WebDriver::Error::StaleElementReferenceError`
|
56
|
+
# Case the exception is raised it is reloaded the dom of the object
|
57
|
+
#
|
58
|
+
# @param block [Block] The block of code to be executed
|
59
|
+
def cover(&block)
|
60
|
+
block.call
|
61
|
+
rescue Selenium::WebDriver::Error::StaleElementReferenceError
|
62
|
+
load_dom
|
63
|
+
retry
|
64
|
+
end
|
37
65
|
end
|
38
66
|
end
|
data/selenium_record.gemspec
CHANGED
@@ -23,13 +23,17 @@ desc
|
|
23
23
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
24
24
|
spec.require_paths = ['lib']
|
25
25
|
|
26
|
+
spec.add_runtime_dependency 'activesupport', '~> 3.2.0'
|
27
|
+
|
26
28
|
spec.add_development_dependency 'bundler', '~> 1.6'
|
29
|
+
spec.add_development_dependency 'cane', '~> 2.6.2'
|
30
|
+
spec.add_development_dependency 'codeclimate-test-reporter', '~> 0.4.3'
|
31
|
+
spec.add_development_dependency 'coveralls', '~> 0.7.2'
|
32
|
+
spec.add_development_dependency 'pry'
|
33
|
+
spec.add_development_dependency 'pry-byebug'
|
27
34
|
spec.add_development_dependency 'rake'
|
35
|
+
spec.add_development_dependency 'reek'
|
28
36
|
spec.add_development_dependency 'rspec'
|
29
|
-
spec.add_development_dependency 'codeclimate-test-reporter'
|
30
|
-
spec.add_development_dependency 'simplecov'
|
31
|
-
spec.add_development_dependency 'coveralls'
|
32
37
|
spec.add_development_dependency 'rubocop'
|
33
|
-
spec.add_development_dependency '
|
34
|
-
spec.add_development_dependency 'cane'
|
38
|
+
spec.add_development_dependency 'simplecov'
|
35
39
|
end
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: seleniumrecord
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2.revision
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Saenz Tagarro
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-12-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 3.2.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 3.2.0
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: bundler
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -25,21 +39,49 @@ dependencies:
|
|
25
39
|
- !ruby/object:Gem::Version
|
26
40
|
version: '1.6'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
42
|
+
name: cane
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
30
44
|
requirements:
|
31
|
-
- - "
|
45
|
+
- - "~>"
|
32
46
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
47
|
+
version: 2.6.2
|
34
48
|
type: :development
|
35
49
|
prerelease: false
|
36
50
|
version_requirements: !ruby/object:Gem::Requirement
|
37
51
|
requirements:
|
38
|
-
- - "
|
52
|
+
- - "~>"
|
39
53
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
54
|
+
version: 2.6.2
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
56
|
+
name: codeclimate-test-reporter
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.4.3
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 0.4.3
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: coveralls
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 0.7.2
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 0.7.2
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: pry
|
43
85
|
requirement: !ruby/object:Gem::Requirement
|
44
86
|
requirements:
|
45
87
|
- - ">="
|
@@ -53,7 +95,7 @@ dependencies:
|
|
53
95
|
- !ruby/object:Gem::Version
|
54
96
|
version: '0'
|
55
97
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
98
|
+
name: pry-byebug
|
57
99
|
requirement: !ruby/object:Gem::Requirement
|
58
100
|
requirements:
|
59
101
|
- - ">="
|
@@ -67,7 +109,7 @@ dependencies:
|
|
67
109
|
- !ruby/object:Gem::Version
|
68
110
|
version: '0'
|
69
111
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
112
|
+
name: rake
|
71
113
|
requirement: !ruby/object:Gem::Requirement
|
72
114
|
requirements:
|
73
115
|
- - ">="
|
@@ -81,7 +123,7 @@ dependencies:
|
|
81
123
|
- !ruby/object:Gem::Version
|
82
124
|
version: '0'
|
83
125
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
126
|
+
name: reek
|
85
127
|
requirement: !ruby/object:Gem::Requirement
|
86
128
|
requirements:
|
87
129
|
- - ">="
|
@@ -95,7 +137,7 @@ dependencies:
|
|
95
137
|
- !ruby/object:Gem::Version
|
96
138
|
version: '0'
|
97
139
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
140
|
+
name: rspec
|
99
141
|
requirement: !ruby/object:Gem::Requirement
|
100
142
|
requirements:
|
101
143
|
- - ">="
|
@@ -109,7 +151,7 @@ dependencies:
|
|
109
151
|
- !ruby/object:Gem::Version
|
110
152
|
version: '0'
|
111
153
|
- !ruby/object:Gem::Dependency
|
112
|
-
name:
|
154
|
+
name: rubocop
|
113
155
|
requirement: !ruby/object:Gem::Requirement
|
114
156
|
requirements:
|
115
157
|
- - ">="
|
@@ -123,7 +165,7 @@ dependencies:
|
|
123
165
|
- !ruby/object:Gem::Version
|
124
166
|
version: '0'
|
125
167
|
- !ruby/object:Gem::Dependency
|
126
|
-
name:
|
168
|
+
name: simplecov
|
127
169
|
requirement: !ruby/object:Gem::Requirement
|
128
170
|
requirements:
|
129
171
|
- - ">="
|
@@ -146,15 +188,27 @@ extensions: []
|
|
146
188
|
extra_rdoc_files: []
|
147
189
|
files:
|
148
190
|
- ".gitignore"
|
191
|
+
- ".pryrc"
|
192
|
+
- ".ruby-gemset"
|
193
|
+
- ".ruby-version"
|
194
|
+
- CHANGELOG.md
|
149
195
|
- Gemfile
|
150
196
|
- LICENSE.txt
|
151
197
|
- README.md
|
152
198
|
- Rakefile
|
199
|
+
- lib/generators/selenium_record/install_generator.rb
|
200
|
+
- lib/generators/selenium_record/templates/autoload.rb.erb
|
201
|
+
- lib/generators/selenium_record/templates/base/application_navigation_component.rb.erb
|
202
|
+
- lib/generators/selenium_record/templates/base/application_page.rb.erb
|
203
|
+
- lib/generators/selenium_record/templates/base/application_view.rb.erb
|
204
|
+
- lib/generators/selenium_record/templates/selenium_record.rb.erb
|
153
205
|
- lib/selenium_record.rb
|
154
206
|
- lib/selenium_record/action_builder.rb
|
155
207
|
- lib/selenium_record/actions.rb
|
208
|
+
- lib/selenium_record/axiable.rb
|
156
209
|
- lib/selenium_record/axis.rb
|
157
210
|
- lib/selenium_record/base.rb
|
211
|
+
- lib/selenium_record/component_autoload.rb
|
158
212
|
- lib/selenium_record/configuration.rb
|
159
213
|
- lib/selenium_record/core.rb
|
160
214
|
- lib/selenium_record/html.rb
|