seleniumrecord 0.0.1.beta1 → 0.0.2.revision
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
[![Gem Version](https://badge.fury.io/rb/
|
1
|
+
[![Gem Version](https://badge.fury.io/rb/seleniumrecord.svg)](http://badge.fury.io/rb/seleniumrecord)
|
2
2
|
[![Code Climate](https://codeclimate.com/github/dsaenztagarro/selenium-record/badges/gpa.svg)](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
|