marta 0.26150
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 +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
|