marta 0.26150
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +12 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/CODE_OF_CONDUCT.md +49 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +299 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/example_project/p_object/test_page.rb +31 -0
- data/example_project/spec/p_object/pageobjects/MartaTestPage.json +1 -0
- data/example_project/spec/spec_helper.rb +11 -0
- data/example_project/spec/watir_test_page_spec.rb +12 -0
- data/example_project/tests_with_learning.sh +1 -0
- data/example_project/tests_without_learning.sh +1 -0
- data/lib/marta/black_magic.rb +147 -0
- data/lib/marta/classes_creation.rb +21 -0
- data/lib/marta/data/custom-xpath.html +22 -0
- data/lib/marta/data/custom-xpath.js +48 -0
- data/lib/marta/data/element-confirm.html +18 -0
- data/lib/marta/data/element-confirm.js +30 -0
- data/lib/marta/data/element.html +23 -0
- data/lib/marta/data/element.js +183 -0
- data/lib/marta/data/for_test.html +7 -0
- data/lib/marta/data/for_test.js +8 -0
- data/lib/marta/data/page.html +24 -0
- data/lib/marta/data/page.js +38 -0
- data/lib/marta/data/style.css +209 -0
- data/lib/marta/dialogs.rb +124 -0
- data/lib/marta/injector.rb +101 -0
- data/lib/marta/json_2_class.rb +145 -0
- data/lib/marta/lightning.rb +36 -0
- data/lib/marta/options_and_paths.rb +140 -0
- data/lib/marta/public_methods.rb +51 -0
- data/lib/marta/read_write.rb +44 -0
- data/lib/marta/simple_element_finder.rb +84 -0
- data/lib/marta/user_values_prework.rb +26 -0
- data/lib/marta/version.rb +4 -0
- data/lib/marta/x_path.rb +170 -0
- data/lib/marta.rb +62 -0
- data/marta.gemspec +28 -0
- metadata +156 -0
@@ -0,0 +1,124 @@
|
|
1
|
+
require 'marta/simple_element_finder'
|
2
|
+
require 'marta/x_path'
|
3
|
+
require 'marta/lightning'
|
4
|
+
require 'marta/injector'
|
5
|
+
require 'marta/public_methods'
|
6
|
+
module Marta
|
7
|
+
|
8
|
+
#
|
9
|
+
# All many-steps dialogs should be here
|
10
|
+
#
|
11
|
+
# There is at least one situation when getting info from user is not so simple
|
12
|
+
# We need dialogs for cases like that. Now there is only dialog about method
|
13
|
+
module Dialogs
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
#
|
18
|
+
# Dialog operator class
|
19
|
+
#
|
20
|
+
# @note It is believed that no user will use it
|
21
|
+
class MethodSpeaker
|
22
|
+
|
23
|
+
include XPath, Lightning, Injector, PublicMethods
|
24
|
+
|
25
|
+
def initialize(class_name, method_name, data, requestor)
|
26
|
+
@class_name = class_name
|
27
|
+
@method_name = method_name
|
28
|
+
@data = data
|
29
|
+
@title = class_name+ '.' + method_name.to_s
|
30
|
+
@requestor = requestor
|
31
|
+
end
|
32
|
+
|
33
|
+
# Standart question
|
34
|
+
def ask(what, title = 'Some title', data = Hash.new)
|
35
|
+
inject(what, title, data)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Main method. All the dialog logic is here
|
39
|
+
def dialog
|
40
|
+
while !finished? do
|
41
|
+
@attrs = ask_for_elements
|
42
|
+
@mass = get_elements_by_attrs
|
43
|
+
@styles = mass_highlight_turn @mass
|
44
|
+
@result = ask_confirmation
|
45
|
+
mass_highlight_turn(@mass, false, @styles)
|
46
|
+
end
|
47
|
+
if @result == '1'
|
48
|
+
standart_meth_merge
|
49
|
+
else
|
50
|
+
xpath_meth_merge
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Asking: "What are you looking for?"
|
55
|
+
def ask_for_elements
|
56
|
+
ask 'element', @title, @data['meths'][@method_name]
|
57
|
+
end
|
58
|
+
|
59
|
+
# Creating data to save when it is a basically defined element
|
60
|
+
def standart_meth_merge
|
61
|
+
temp = temp_hash
|
62
|
+
temp['meths'][@method_name] = @attrs
|
63
|
+
@data['meths'].merge!(temp['meths'])
|
64
|
+
@data
|
65
|
+
end
|
66
|
+
|
67
|
+
# Creating data to save when user suggests a custom xpath
|
68
|
+
def xpath_meth_merge
|
69
|
+
temp = temp_hash
|
70
|
+
temp['meths'][@method_name]['options'] = @result
|
71
|
+
@data['meths'].merge!(temp['meths'])
|
72
|
+
@data
|
73
|
+
end
|
74
|
+
|
75
|
+
# Finding out what was selected
|
76
|
+
def get_elements_by_attrs
|
77
|
+
xpath = XPathFactory.new(@attrs, @requestor).generate_xpath
|
78
|
+
engine.elements(xpath: xpath)
|
79
|
+
end
|
80
|
+
|
81
|
+
# Asking: "Are you sure?"
|
82
|
+
def ask_confirmation
|
83
|
+
ask 'element-confirm', @title, @mass.length.to_s
|
84
|
+
end
|
85
|
+
|
86
|
+
# Asking: "Provide your xpath"
|
87
|
+
def ask_xpath
|
88
|
+
ask 'custom-xpath', @title
|
89
|
+
end
|
90
|
+
|
91
|
+
#
|
92
|
+
# Is dialog finished?
|
93
|
+
#
|
94
|
+
# JS returning '1' when it's done. That is not good
|
95
|
+
# and should be rewrited as soon as possible
|
96
|
+
def finished?
|
97
|
+
if @result == '1'
|
98
|
+
true
|
99
|
+
elsif @result == '3'
|
100
|
+
@result = ask_xpath
|
101
|
+
(@result != '2') ? true : false
|
102
|
+
else
|
103
|
+
false
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# Forming of an empty hash for storing element info
|
108
|
+
def temp_hash
|
109
|
+
temp, temp['meths'], temp['meths'][@method_name],
|
110
|
+
temp['meths'][@method_name]['options'] = Hash.new, Hash.new, Hash.new,
|
111
|
+
Hash.new
|
112
|
+
temp
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
# Method definition process
|
117
|
+
def user_method_dialogs(my_class_name, method_name, data)
|
118
|
+
dialog_master = MethodSpeaker.new(my_class_name, method_name, data, self)
|
119
|
+
data = dialog_master.dialog
|
120
|
+
file_write(my_class_name.to_s, data)
|
121
|
+
data
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
module Marta
|
2
|
+
|
3
|
+
#
|
4
|
+
# This module can add Marta's stuff to the page.
|
5
|
+
#
|
6
|
+
# Marta is inserting tons of stuff to the pages!
|
7
|
+
# Those insertions are the only way for her to perform dialog with user
|
8
|
+
module Injector
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
#
|
13
|
+
# We are injecting things to the page using the Syringe.
|
14
|
+
#
|
15
|
+
# @note It is believed that no user will use it
|
16
|
+
class Syringe
|
17
|
+
|
18
|
+
def initialize(engine, marta_what, title = 'Something important',
|
19
|
+
old_data = Hash.new, folder = gem_libdir)
|
20
|
+
@what = marta_what
|
21
|
+
@title = title
|
22
|
+
@data = old_data
|
23
|
+
@engine = engine
|
24
|
+
@folder = folder
|
25
|
+
end
|
26
|
+
|
27
|
+
# "first" or "last".
|
28
|
+
def get_where(first)
|
29
|
+
first ? "first" : "last"
|
30
|
+
end
|
31
|
+
|
32
|
+
# Inserting to the page
|
33
|
+
def insert_to_page(tag, inner, first = true)
|
34
|
+
where = get_where(first)
|
35
|
+
script = <<-JS
|
36
|
+
var newMartaObject = document.createElement('#{tag}');
|
37
|
+
newMartaObject.setAttribute('martaclass','marta_#{tag}');
|
38
|
+
newMartaObject.innerHTML = '#{inner}';
|
39
|
+
document.body.insertBefore(newMartaObject,document.body.#{where}Child);
|
40
|
+
JS
|
41
|
+
@engine.execute_script script.gsub("\n",'')
|
42
|
+
end
|
43
|
+
|
44
|
+
# Taking a correct js file to inject
|
45
|
+
def js
|
46
|
+
File.read(@folder + "/data/#{@what}.js").gsub("\n",'')
|
47
|
+
end
|
48
|
+
|
49
|
+
# Taking a correct html file to inject
|
50
|
+
def html
|
51
|
+
File.read(@folder + "/data/#{@what}.html").gsub("\n",'')
|
52
|
+
end
|
53
|
+
|
54
|
+
# Taking a correct css file to inject
|
55
|
+
def style
|
56
|
+
File.read(@folder + "/data/style.css").gsub("\n",'')
|
57
|
+
end
|
58
|
+
|
59
|
+
# Injecting everything to the page
|
60
|
+
def files_to_page
|
61
|
+
insert_to_page('div', html)
|
62
|
+
insert_to_page('script', js, false)
|
63
|
+
insert_to_page('style', style, false)
|
64
|
+
end
|
65
|
+
|
66
|
+
# It is never used without get_result.
|
67
|
+
# But it can be used to show some message for user
|
68
|
+
def actual_injection
|
69
|
+
files_to_page
|
70
|
+
@data ||= Hash.new
|
71
|
+
insert_to_page('script', "var marta_what = \"#{@title}\"", false)
|
72
|
+
insert_to_page('script', "var old_marta_Data = #{@data}".gsub('=>',':'),
|
73
|
+
false)
|
74
|
+
@engine.execute_script("marta_add_data();")
|
75
|
+
end
|
76
|
+
|
77
|
+
# Retrieving result if js var = marta_confirm_mark is true
|
78
|
+
# we are returning js var = marta_result. So custom js should always
|
79
|
+
# return both.
|
80
|
+
def get_result
|
81
|
+
result = false
|
82
|
+
while result != true
|
83
|
+
# When Marta can't get a result she is reinjecting her stuff
|
84
|
+
begin
|
85
|
+
result = @engine.execute_script("return marta_confirm_mark")
|
86
|
+
rescue
|
87
|
+
actual_injection
|
88
|
+
end
|
89
|
+
end
|
90
|
+
@engine.execute_script("return marta_result")
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# That's how Marta is injecting and retrieving result
|
95
|
+
def inject(what, title = 'Something important', data = Hash.new)
|
96
|
+
syringe = Syringe.new(engine, what, title, data, gem_libdir)
|
97
|
+
syringe.actual_injection
|
98
|
+
syringe.get_result
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,145 @@
|
|
1
|
+
require 'marta/options_and_paths'
|
2
|
+
require 'marta/read_write'
|
3
|
+
module Marta
|
4
|
+
|
5
|
+
#
|
6
|
+
# Here Marta is reading json files and precreating pageobject classes
|
7
|
+
# which were defined previously
|
8
|
+
#
|
9
|
+
# Main trick of the Marta is parsing jsons files to classes.
|
10
|
+
# For example valid Foo.json file in a valid folder will turn into Foo class.
|
11
|
+
# Class content differs when Marta is set to learning mode and when it's not.
|
12
|
+
# Class will have methods = watir elements
|
13
|
+
# and vars = user defined vars with default values.
|
14
|
+
# Class will not accept any arguments for generated methods.
|
15
|
+
# The class will have default initialize method, engine method.
|
16
|
+
#
|
17
|
+
# Also the class can has method_edit method. In theory it can be called like
|
18
|
+
# Foo.method_edit('new_method_name').
|
19
|
+
# It should define new method even if learn mode is disabled.
|
20
|
+
# But I am never using such construction :)
|
21
|
+
# In learn mode any unknown method will cause dialog that will ask user about
|
22
|
+
# what element should be used.
|
23
|
+
#
|
24
|
+
# Also for each method foo method foo_exact will be created and vice versa.
|
25
|
+
# Method wich ends with exact will use strict element searching scheme.
|
26
|
+
module Json2Class
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
#
|
31
|
+
# To create a special class we are using a special class
|
32
|
+
#
|
33
|
+
# @note It is believed that no user will use it
|
34
|
+
class SmartPageCreator
|
35
|
+
|
36
|
+
include OptionsAndPaths, ReadWrite
|
37
|
+
|
38
|
+
#
|
39
|
+
# Main class creation method. SmartPage method is only working with
|
40
|
+
# a proper initialization.
|
41
|
+
#
|
42
|
+
# By default SmartPage has no initialization which is making it almost
|
43
|
+
# useles while not constructed like that. It will be fixed.
|
44
|
+
def self.create(class_name, data, edit)
|
45
|
+
c = Class.new(SmartPage) do
|
46
|
+
define_method :initialize do |my_data=data, my_class_name=class_name,
|
47
|
+
will_edit=edit|
|
48
|
+
@data = my_data
|
49
|
+
@class_name = class_name
|
50
|
+
@edit_mark = will_edit
|
51
|
+
build_content my_data
|
52
|
+
if will_edit
|
53
|
+
page_edit my_class_name, my_data
|
54
|
+
end
|
55
|
+
# We need optimization here very much!
|
56
|
+
build_content my_data
|
57
|
+
end
|
58
|
+
end
|
59
|
+
# We are vanishing previous version of class
|
60
|
+
if Kernel.constants.include?(class_name.to_sym)
|
61
|
+
Kernel.send(:remove_const, class_name.to_sym)
|
62
|
+
end
|
63
|
+
# We are declaring our class
|
64
|
+
Kernel.const_set class_name, c
|
65
|
+
end
|
66
|
+
|
67
|
+
# We are parsing file into a class
|
68
|
+
def self.json_2_class(json, edit_enabled = true)
|
69
|
+
data = ReaderWriter.file_2_hash(json)
|
70
|
+
if !data.nil?
|
71
|
+
class_name = File.basename(json, ".*")
|
72
|
+
edit_mark = SettingMaster.learn_status and edit_enabled
|
73
|
+
create class_name, data, edit_mark
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# Marta is parsing all the files in pageobject folder into classes
|
78
|
+
def self.create_all
|
79
|
+
if File.directory?(SettingMaster.pageobjects_folder)
|
80
|
+
Dir["#{SettingMaster.pageobjects_folder}/*.json"].each do |file_name|
|
81
|
+
json_2_class(file_name, true) #true here
|
82
|
+
end
|
83
|
+
else
|
84
|
+
FileUtils::mkdir_p SettingMaster.pageobjects_folder
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def read_folder
|
90
|
+
SmartPageCreator.create_all
|
91
|
+
end
|
92
|
+
|
93
|
+
def json_2_class(json, edit_enabled = true)
|
94
|
+
SmartPageCreator.json_2_class(json, edit_enabled)
|
95
|
+
end
|
96
|
+
|
97
|
+
def build_content(data)
|
98
|
+
build_methods(data['meths'])
|
99
|
+
build_vars(data['vars'])
|
100
|
+
end
|
101
|
+
|
102
|
+
def build_methods(methods)
|
103
|
+
methods.each_pair do |method_name, content|
|
104
|
+
build_method method_name, content
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def build_vars(vars)
|
109
|
+
vars.each do |var_name, default_value|
|
110
|
+
build_var var_name, default_value
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def build_method(name, content)
|
115
|
+
define_singleton_method name.to_sym do
|
116
|
+
learn_status ? method_edit(name) : marta_magic_finder(content)
|
117
|
+
end
|
118
|
+
exact = name + '_exact'
|
119
|
+
define_singleton_method exact.to_sym do
|
120
|
+
learn_status ? method_edit(exact) : marta_simple_finder(content)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def build_var(name, content)
|
125
|
+
if !self.methods.include?(name.to_sym) and (@data['meths'][name] == nil)
|
126
|
+
self.singleton_class.send(:attr_accessor, name.to_sym)
|
127
|
+
instance_variable_set("@#{name}", process_string(content))
|
128
|
+
else
|
129
|
+
if !@data['meths'][name].nil?
|
130
|
+
warn "Marta will not create '#{name}' variable for #{self.class}"\
|
131
|
+
" since it is already in use by method"
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def correct_name(name)
|
137
|
+
if name.to_s.end_with? "_exact"
|
138
|
+
method_name = name.to_s[0..-7]
|
139
|
+
else
|
140
|
+
method_name = name.to_s
|
141
|
+
end
|
142
|
+
method_name
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Marta
|
2
|
+
|
3
|
+
# Marta can highlight or unhighlight elements when her styles are injected.
|
4
|
+
module Lightning
|
5
|
+
|
6
|
+
private
|
7
|
+
|
8
|
+
# We can highlight an element
|
9
|
+
def highlight(element)
|
10
|
+
orig_style = element.attribute_value("style")
|
11
|
+
engine.execute_script("arguments[0].setAttribute(arguments[1],"\
|
12
|
+
" arguments[2])", element, "style",
|
13
|
+
"animation: marta_found 6s infinite;")
|
14
|
+
orig_style
|
15
|
+
end
|
16
|
+
|
17
|
+
# We can unhighlight an element
|
18
|
+
def unhighlight(element, style)
|
19
|
+
engine.execute_script("arguments[0].setAttribute(arguments[1],"\
|
20
|
+
" arguments[2])", element, "style", style)
|
21
|
+
end
|
22
|
+
|
23
|
+
# We can highlight\unhighlight tons of elements at once
|
24
|
+
def mass_highlight_turn(mass, turn_on = true, styles = nil)
|
25
|
+
result = Array.new
|
26
|
+
mass.each_with_index do |element, i|
|
27
|
+
if turn_on
|
28
|
+
result[i] = highlight(element)
|
29
|
+
else
|
30
|
+
unhighlight(element, styles[i])
|
31
|
+
end
|
32
|
+
end
|
33
|
+
result
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
module Marta
|
2
|
+
|
3
|
+
#
|
4
|
+
# Marta can store and return settings which may differ for each thread
|
5
|
+
#
|
6
|
+
# Settings for Marta.
|
7
|
+
# Most of them could be changed in action using dance_with.
|
8
|
+
# Most of them are thread dependant.
|
9
|
+
module OptionsAndPaths
|
10
|
+
|
11
|
+
#
|
12
|
+
# We are storing vars in a special class
|
13
|
+
#
|
14
|
+
# @note It is believed that no user will use it
|
15
|
+
class SettingMaster
|
16
|
+
@@folder = Hash.new
|
17
|
+
@@tolerancy = Hash.new
|
18
|
+
@@learn = Hash.new
|
19
|
+
@@engine = Hash.new
|
20
|
+
|
21
|
+
# Getting uniq id for process thread
|
22
|
+
def self.thread_id
|
23
|
+
Thread.current.object_id
|
24
|
+
end
|
25
|
+
|
26
|
+
# Checking default learn option status
|
27
|
+
def self.learn_option
|
28
|
+
ENV['LEARN'].nil? ? false : true
|
29
|
+
end
|
30
|
+
|
31
|
+
# Marta knows does she learn or not.
|
32
|
+
def self.learn_status
|
33
|
+
if @@learn[thread_id].nil?
|
34
|
+
learn_option
|
35
|
+
else
|
36
|
+
@@learn[thread_id]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Marta knows where are her saved generated pageobjects
|
41
|
+
def self.pageobjects_folder
|
42
|
+
@@folder[thread_id]
|
43
|
+
end
|
44
|
+
|
45
|
+
# Marta knows how hard she should search for elements
|
46
|
+
def self.tolerancy_value
|
47
|
+
@@tolerancy[thread_id]
|
48
|
+
end
|
49
|
+
|
50
|
+
# engine (analog of browser) is a setting too
|
51
|
+
def self.engine
|
52
|
+
@@engine[thread_id]
|
53
|
+
end
|
54
|
+
|
55
|
+
# Marta is changing parameters by the same scheme.
|
56
|
+
def self.parameter_set(what, value, default)
|
57
|
+
what[thread_id] = !value.nil? ? value : what[thread_id]
|
58
|
+
what[thread_id] = what[thread_id].nil? ? default : what[thread_id]
|
59
|
+
what
|
60
|
+
end
|
61
|
+
|
62
|
+
# Marta locates iframes sometimes
|
63
|
+
def self.iframe_locate
|
64
|
+
if !engine.nil?
|
65
|
+
if engine.class == Watir::IFrame
|
66
|
+
engine.locate
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# Marta is switching to iframes sometimes
|
72
|
+
def self.iframe_switch_to
|
73
|
+
if !engine.nil?
|
74
|
+
if engine.class == Watir::IFrame
|
75
|
+
engine.switch_to!
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# Marta is setting engine by pretty comlex rules
|
81
|
+
def self.set_engine(value)
|
82
|
+
iframe_locate
|
83
|
+
@@engine = parameter_set(@@engine, value, nil)
|
84
|
+
iframe_switch_to
|
85
|
+
if engine.nil?
|
86
|
+
@@engine = parameter_set(@@engine, value, Watir::Browser.new(:chrome))
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
# Marta uses simple rules to set the folder
|
91
|
+
def self.set_folder(value)
|
92
|
+
@@folder = parameter_set(@@folder, value, 'Marta_s_pageobjects')
|
93
|
+
end
|
94
|
+
|
95
|
+
# Marta uses simple rules to set the laearn mode
|
96
|
+
def self.set_learn(value)
|
97
|
+
@@learn = parameter_set(@@learn, value, learn_option)
|
98
|
+
end
|
99
|
+
|
100
|
+
# Marta uses simple rules to set the tolerancy value
|
101
|
+
def self.set_tolerancy(value)
|
102
|
+
@@tolerancy = parameter_set(@@tolerancy, value, 1024)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
private
|
107
|
+
|
108
|
+
# Defining the place for files to inject to browser
|
109
|
+
def gem_libdir
|
110
|
+
t = ["#{File.dirname(File.expand_path($0))}/../lib/#{Marta::NAME}",
|
111
|
+
"#{Gem.dir}/gems/#{Marta::NAME}-#{Marta::VERSION}/lib/#{Marta::NAME}"]
|
112
|
+
t.each {|i| return i if File.readable?(i) }
|
113
|
+
end
|
114
|
+
|
115
|
+
# Marta knows does she learn or not.
|
116
|
+
def learn_status
|
117
|
+
SettingMaster.learn_status
|
118
|
+
end
|
119
|
+
|
120
|
+
# Marta knows where are her saved generated pageobjects
|
121
|
+
def pageobjects_folder
|
122
|
+
SettingMaster.pageobjects_folder
|
123
|
+
end
|
124
|
+
|
125
|
+
# Marta knows how hard she should search for elements
|
126
|
+
def tolerancy_value
|
127
|
+
SettingMaster.tolerancy_value
|
128
|
+
end
|
129
|
+
|
130
|
+
# Marta is accepting parameters and rereading pageobjects on any change
|
131
|
+
def dance_with(browser: nil, folder: nil, learn: nil, tolerancy: nil)
|
132
|
+
SettingMaster.set_engine browser
|
133
|
+
SettingMaster.set_folder folder
|
134
|
+
SettingMaster.set_learn learn
|
135
|
+
read_folder
|
136
|
+
SettingMaster.set_tolerancy tolerancy
|
137
|
+
engine
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'marta/options_and_paths'
|
2
|
+
module Marta
|
3
|
+
|
4
|
+
# Methods that user can use out of the box in SmartPage
|
5
|
+
module PublicMethods
|
6
|
+
|
7
|
+
include OptionsAndPaths
|
8
|
+
|
9
|
+
# User can define a method for example in a middle of a debug session
|
10
|
+
def method_edit(name)
|
11
|
+
method_name = correct_name(name)
|
12
|
+
exact_name = method_name.to_s + "_exact"
|
13
|
+
data = user_method_dialogs(@class_name, method_name, @data)
|
14
|
+
define_singleton_method method_name.to_sym do |meth_content=@data['meths'][method_name]|
|
15
|
+
marta_magic_finder(meth_content)
|
16
|
+
end
|
17
|
+
define_singleton_method exact_name.to_sym do |meth_content=@data['meths'][method_name]|
|
18
|
+
marta_simple_finder(meth_content)
|
19
|
+
end
|
20
|
+
public_send name.to_sym
|
21
|
+
end
|
22
|
+
|
23
|
+
# User can get engine (normally browser instance or iframe element)
|
24
|
+
def engine
|
25
|
+
SettingMaster.engine
|
26
|
+
end
|
27
|
+
|
28
|
+
# If page has url variable it can be opened like Page.new.open_page
|
29
|
+
def open_page(url = nil)
|
30
|
+
if url != nil
|
31
|
+
engine.goto url
|
32
|
+
else
|
33
|
+
if @url == nil
|
34
|
+
raise ArgumentError, "You should set url to use open_page"
|
35
|
+
end
|
36
|
+
engine.goto @url
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
alias_method :default_method_missing, :method_missing
|
41
|
+
|
42
|
+
# method missing hijacking It should be used only for SmartPage
|
43
|
+
def method_missing(method_name, *args, &block)
|
44
|
+
if learn_status
|
45
|
+
method_edit(method_name)# , *args, &block)
|
46
|
+
else
|
47
|
+
default_method_missing(method_name, *args, &block)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'marta/options_and_paths'
|
2
|
+
module Marta
|
3
|
+
|
4
|
+
# Marta has very simple read\write actions
|
5
|
+
module ReadWrite
|
6
|
+
|
7
|
+
private
|
8
|
+
|
9
|
+
#
|
10
|
+
# Sometimes marta reads files. Sometimes writes
|
11
|
+
#
|
12
|
+
# @note It is believed that no user will use it
|
13
|
+
class ReaderWriter
|
14
|
+
include OptionsAndPaths
|
15
|
+
# Marta is writing to jsons from time to time
|
16
|
+
def self.file_write(name, data)
|
17
|
+
file_name = File.join(SettingMaster.pageobjects_folder, name + '.json')
|
18
|
+
File.open(file_name,"w") do |f|
|
19
|
+
f.write(data.to_json)
|
20
|
+
end
|
21
|
+
file_name
|
22
|
+
end
|
23
|
+
|
24
|
+
# Marta reads file to hash if it is a valid json
|
25
|
+
# If it is not a json file Marta will treat it like nothing
|
26
|
+
def self.file_2_hash(json)
|
27
|
+
begin
|
28
|
+
file = File.read(json)
|
29
|
+
data = JSON.parse(file)
|
30
|
+
rescue
|
31
|
+
nil
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def file_write(name, data)
|
37
|
+
ReaderWriter.file_write(name, data)
|
38
|
+
end
|
39
|
+
|
40
|
+
def file_2_hash(json)
|
41
|
+
ReaderWriter.file_2_hash(json)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|