locatine 0.02637 → 0.02651

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +268 -297
  3. data/bin/locatine-daemon.rb +4 -2
  4. data/lib/locatine/daemon.rb +44 -60
  5. data/lib/locatine/daemon_helpers/methods.rb +85 -0
  6. data/lib/locatine/element.rb +28 -0
  7. data/lib/locatine/results.rb +125 -0
  8. data/lib/locatine/results_helpers/common.rb +68 -0
  9. data/lib/locatine/results_helpers/find_by_magic.rb +106 -0
  10. data/lib/locatine/results_helpers/guess.rb +45 -0
  11. data/lib/locatine/results_helpers/info_generator.rb +79 -0
  12. data/lib/locatine/results_helpers/logger.rb +64 -0
  13. data/lib/locatine/{for_search → results_helpers}/xpath_generator.rb +18 -19
  14. data/lib/locatine/scripts/element.js +40 -0
  15. data/lib/locatine/scripts/page.js +53 -0
  16. data/lib/locatine/scripts/parent.js +6 -0
  17. data/lib/locatine/session.rb +102 -0
  18. data/lib/locatine/version.rb +4 -2
  19. data/lib/locatine.rb +3 -2
  20. metadata +39 -49
  21. data/lib/locatine/app/background.js +0 -8
  22. data/lib/locatine/app/content.css +0 -38
  23. data/lib/locatine/app/content.js +0 -152
  24. data/lib/locatine/app/devtools.html +0 -1
  25. data/lib/locatine/app/devtools.js +0 -3
  26. data/lib/locatine/app/manifest.json +0 -20
  27. data/lib/locatine/app/popup.css +0 -47
  28. data/lib/locatine/app/popup.html +0 -19
  29. data/lib/locatine/app/popup.js +0 -65
  30. data/lib/locatine/daemon_helpers.rb +0 -52
  31. data/lib/locatine/for_search/data_generate.rb +0 -67
  32. data/lib/locatine/for_search/data_logic.rb +0 -98
  33. data/lib/locatine/for_search/defaults.rb +0 -40
  34. data/lib/locatine/for_search/dialog_logic.rb +0 -107
  35. data/lib/locatine/for_search/element_selection.rb +0 -80
  36. data/lib/locatine/for_search/file_work.rb +0 -67
  37. data/lib/locatine/for_search/find_by_guess.rb +0 -67
  38. data/lib/locatine/for_search/find_by_locator.rb +0 -59
  39. data/lib/locatine/for_search/find_by_magic.rb +0 -65
  40. data/lib/locatine/for_search/find_logic.rb +0 -79
  41. data/lib/locatine/for_search/helpers.rb +0 -106
  42. data/lib/locatine/for_search/highlight.rb +0 -41
  43. data/lib/locatine/for_search/listening.rb +0 -48
  44. data/lib/locatine/for_search/merge.rb +0 -40
  45. data/lib/locatine/for_search/name_helper.rb +0 -51
  46. data/lib/locatine/for_search/page_work.rb +0 -126
  47. data/lib/locatine/for_search/public.rb +0 -179
  48. data/lib/locatine/for_search/saying.rb +0 -199
  49. data/lib/locatine/for_search.rb +0 -6
  50. data/lib/locatine/large_scripts/css.js +0 -21
  51. data/lib/locatine/large_scripts/dimensions.js +0 -17
  52. data/lib/locatine/large_scripts/element.js +0 -30
  53. data/lib/locatine/large_scripts/page.js +0 -60
  54. data/lib/locatine/scope.rb +0 -88
  55. data/lib/locatine/search.rb +0 -67
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'colorize'
4
+
5
+ module Locatine
6
+ module ResultsHelpers
7
+ #
8
+ # Methods for sending lines to STDOUT
9
+ module Logger
10
+ def warn(text)
11
+ puts "WARNING: #{Time.now}: ".yellow + text
12
+ end
13
+
14
+ def log(text)
15
+ puts "MESSAGE: #{Time.now}: ".magenta + text
16
+ end
17
+
18
+ def locatine_error(text)
19
+ puts "ERROR: #{Time.now}: ".red + text.red
20
+ end
21
+
22
+ def warn_locator
23
+ warn("Locator is broken. For #{name} by"\
24
+ " #{@locator['using']}>>>'#{locator['value']}'")
25
+ end
26
+
27
+ def warn_guess
28
+ warn("Locatine is trying to guess what is #{@name}")
29
+ end
30
+
31
+ def log_start
32
+ log "#{Time.now}: Locatine is working on #{@name}"
33
+ end
34
+
35
+ def warn_magic
36
+ warn "Locatine cannot find element #{@name} by usual methods and "\
37
+ 'starting to look for some element that is similar. Retrived '\
38
+ 'element may be not the one that is desired from this point'
39
+ end
40
+
41
+ def warn_lost
42
+ warn "Locatine found nothing for #{@name}"
43
+ end
44
+
45
+ def warn_unstable_page
46
+ warn 'Locatine detected stale element error. It means some elements'\
47
+ ' found by locatine are not attached to DOM anymore.'\
48
+ ' Page is unstable. Starting searching process again'
49
+ end
50
+
51
+ def log_found
52
+ log "Locatine found something as #{@name}"
53
+ log "XPATH == #{generate_xpath(raw_info)}"
54
+ end
55
+
56
+ def raise_script_error(script, args, answer)
57
+ locatine_error 'Locatine faced an error while trying to perform '\
58
+ "js script.\n ---Script was: #{script}\n\n ---Arguments was: #{args}"\
59
+ "\n\n ---Answer was: #{answer}"
60
+ raise answer['error']
61
+ end
62
+ end
63
+ end
64
+ end
@@ -1,14 +1,22 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Locatine
2
- module ForSearch
4
+ module ResultsHelpers
3
5
  ##
4
6
  # Methods for generation xpath from stored data
5
7
  module XpathGenerator
6
- private
8
+ def find_by_data(base = known)
9
+ xpath = generate_xpath(base)
10
+ @locator = { 'using' => 'xpath', 'value' => xpath }
11
+ simple_find
12
+ end
7
13
 
8
14
  def get_trusted(array)
9
15
  if !array.empty?
10
16
  max = max_stability(array)
11
- (array.select { |i| i['stability'].to_i == max.to_i }).uniq
17
+ (array.select do |i|
18
+ (i['stability'].to_i == max.to_i) && !untrusted.include?(i['name'])
19
+ end).uniq
12
20
  else
13
21
  []
14
22
  end
@@ -21,11 +29,11 @@ module Locatine
21
29
  0
22
30
  end
23
31
 
24
- def generate_xpath(data, vars)
25
- xpath = "[not(@id = 'locatine_magic_div')]"
32
+ def generate_xpath(data)
33
+ xpath = ''
26
34
  data.each_pair do |_depth, array|
27
35
  get_trusted(array).each do |hash|
28
- xpath = generate_xpath_part(hash, vars).to_s + xpath
36
+ xpath = generate_xpath_part(hash).to_s + xpath
29
37
  end
30
38
  xpath = '/*' + xpath
31
39
  end
@@ -33,23 +41,14 @@ module Locatine
33
41
  xpath
34
42
  end
35
43
 
36
- def generate_xpath_part(hash, vars)
37
- result = ''
38
- values = process_string(hash['value'], vars).split(/[,.-_ ;'\\"]/)
39
- values.each do |value|
40
- result += generate_real_xpath_part(hash, value) if !value.empty?
41
- end
42
- result
43
- end
44
-
45
- def generate_real_xpath_part(hash, value)
44
+ def generate_xpath_part(hash)
46
45
  case hash['type']
47
46
  when 'tag'
48
- "[self::#{value}]"
47
+ "[self::#{hash['value']}]"
49
48
  when 'text'
50
- "[contains(text(), '#{value}')]"
49
+ "[contains(text(), '#{hash['value']}')]"
51
50
  when 'attribute'
52
- "[contains(@#{hash['name']}, '#{value}')]"
51
+ "[contains(@#{hash['name']}, '#{hash['value']}')]"
53
52
  end
54
53
  end
55
54
  end
@@ -0,0 +1,40 @@
1
+
2
+ function one_element(target){
3
+
4
+ let element = [];
5
+ let att_array = [];
6
+
7
+ // Taking text
8
+ let text = "";
9
+ if (target.childNodes){
10
+ for (let i = 0; i < target.childNodes.length; ++i){
11
+ if (target.childNodes[i].nodeType === 3){
12
+ text += target.childNodes[i].textContent;
13
+ }
14
+ }
15
+ } else {
16
+ text = target.textContent
17
+ }
18
+ const text_array = text.split(/[\s\'\\]/).filter(word => word !== "");
19
+ for (let i = 0; i < text_array.length; ++i){
20
+ element.push({value: text_array[i], type: "text", name: "text"});
21
+ }
22
+
23
+ //Taking tag
24
+ element.push({value: target.tagName.toLowerCase(), type: "tag", name: "tag"});
25
+
26
+ //Taking attributes
27
+ let atts = target.attributes;
28
+ if (atts) {
29
+ for (let k = 0, n = atts.length; k < n; k++){
30
+ att = atts[k];
31
+ att_array = att.nodeValue.split(/[\s\'\\]/).filter(word => word !== "");
32
+ for (let i = 0; i < att_array.length; ++i){
33
+ element.push({value: att_array[i], type: "attribute", name: att.nodeName});
34
+ }
35
+ }
36
+ }
37
+ return element;
38
+ }
39
+ let x = one_element(arguments[0]);
40
+ return x;
@@ -0,0 +1,53 @@
1
+ function walk(target) {
2
+ let node;
3
+
4
+ const index = everything.indexOf(target);
5
+ let element = [];
6
+ let att_array = [];
7
+ let item = {children: [],
8
+ data: [],
9
+ index: index};
10
+
11
+ // Taking text
12
+ let text = "";
13
+ if (target.childNodes){
14
+ for (let i = 0; i < target.childNodes.length; ++i){
15
+ if (target.childNodes[i].nodeType === 3){
16
+ text += target.childNodes[i].textContent;
17
+ }
18
+ }
19
+ } else {
20
+ text = target.textContent
21
+ }
22
+ const text_array = text.split(/[\s\'\\]/).filter(word => word !== "");
23
+ for (let i = 0; i < text_array.length; ++i){
24
+ element.push({value: text_array[i], type: "text", name: "text"});
25
+ }
26
+
27
+ //Taking tag
28
+ element.push({value: target.tagName.toLowerCase(), type: "tag", name: "tag"});
29
+
30
+ //Taking attributes
31
+ let atts = target.attributes;
32
+ if (atts) {
33
+ for (let k = 0, n = atts.length; k < n; k++){
34
+ att = atts[k];
35
+ att_array = att.nodeValue.split(/[\s\'\\]/).filter(word => word !== "");
36
+ for (let i = 0; i < att_array.length; ++i){
37
+ element.push({value: att_array[i], type: "attribute", name: att.nodeName});
38
+ }
39
+ }
40
+ }
41
+
42
+ // Handle child elements (not magic ones)
43
+ for (node = target.firstChild; node; node = node.nextSibling) {
44
+ if (node.nodeType === 1) { // 1 == Element
45
+ item.children.push(walk(node))
46
+ }
47
+ }
48
+ item.data = element;
49
+ return item;
50
+ }
51
+ const everything = Array.prototype.slice.call( document.getElementsByTagName("*") );
52
+ let result = walk(document.body);
53
+ return [result];
@@ -0,0 +1,6 @@
1
+
2
+ function parent(target){
3
+ return target.parentElement;
4
+ }
5
+ let x = parent(arguments[0]);
6
+ return x;
@@ -0,0 +1,102 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'locatine/results'
4
+ require 'locatine/element'
5
+ require 'locatine/results_helpers/logger'
6
+
7
+ module Locatine
8
+ #
9
+ # Locatine session operator finds and returns
10
+ class Session
11
+ include Locatine::ResultsHelpers::Logger
12
+ attr_accessor :json, :depth, :trusted, :untrusted, :tolerance, :stability,
13
+ :elements, :timeout
14
+
15
+ def defaults
16
+ { json: "#{Dir.pwd}/locatine_files/default.json", depth: 3, trusted: [],
17
+ untrusted: [], tolerance: 50, stability: 10, timeout: 25 }
18
+ end
19
+
20
+ def initialize(selenium, session)
21
+ @selenium = selenium
22
+ @parsed_selenium = URI.parse @selenium
23
+ @session = session
24
+ @elements = []
25
+ @threads = []
26
+ # defaults
27
+ configure defaults
28
+ end
29
+
30
+ def configure(params)
31
+ params.to_h.each_pair do |var, value|
32
+ instance_variable_set("@#{var}", value)
33
+ read if var.to_s == 'json'
34
+ end
35
+ params
36
+ end
37
+
38
+ def read
39
+ dir = File.dirname(@json)
40
+ FileUtils.mkdir_p(dir) unless File.directory?(dir)
41
+ unless File.exist?(@json)
42
+ File.open(@json, 'w') do |f|
43
+ f.write('{"elements" : {}}')
44
+ end
45
+ end
46
+ @elements = JSON.parse(File.read(@json))['elements']
47
+ end
48
+
49
+ def write
50
+ File.open(@json, 'w') do |f|
51
+ f.write(JSON.pretty_generate('elements' => @elements))
52
+ end
53
+ end
54
+
55
+ def find(params, parent = nil)
56
+ results = Results.new
57
+ results.configure(self, params, parent)
58
+ answer = results.find
59
+ @elements[results.name] = results.info unless answer.empty?
60
+ write unless answer.empty?
61
+ answer
62
+ rescue RuntimeError => e
63
+ raise e.message unless e.message == 'stale element reference'
64
+
65
+ warn_unstable_page
66
+ find(params, parent)
67
+ end
68
+
69
+ def execute_script(script, *args)
70
+ args.map! { |item| item.class == Locatine::Element ? item.answer : item }
71
+ value = JSON.parse(api_request('/execute/sync', 'Post',
72
+ { script: script, args: args }
73
+ .to_json).body)['value']
74
+ error_present = (value.class == Hash) && value['error']
75
+ raise_script_error(script, args, value) if error_present
76
+
77
+ value
78
+ end
79
+
80
+ def page
81
+ execute_script(File.read("#{HOME}/scripts/page.js"))
82
+ end
83
+
84
+ def call_uri(path)
85
+ URI::HTTP.build(
86
+ host: @parsed_selenium.host,
87
+ port: @parsed_selenium.port,
88
+ path: "/wd/hub/session/#{@session}#{path}"
89
+ )
90
+ end
91
+
92
+ def api_request(path, method, body)
93
+ uri = call_uri(path)
94
+ req = Net::HTTP.const_get(method)
95
+ .new(uri,
96
+ "Content-Type": 'application/json; charset=utf-8',
97
+ "Cache-Control": 'no-cache')
98
+ req.body = body
99
+ Net::HTTP.new(uri.hostname, uri.port).start { |http| http.request(req) }
100
+ end
101
+ end
102
+ end
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Locatine
2
4
  # constants here...
3
- VERSION = '0.02637'.freeze
4
- NAME = 'locatine'.freeze
5
+ VERSION = '0.02651'
6
+ NAME = 'locatine'
5
7
  HOME = if File.readable?("#{Dir.pwd}/lib/#{Locatine::NAME}")
6
8
  "#{Dir.pwd}/lib/#{Locatine::NAME}"
7
9
  else
data/lib/locatine.rb CHANGED
@@ -1,4 +1,5 @@
1
- require 'locatine/search'
2
- require 'locatine/scope'
1
+ # frozen_string_literal: true
2
+
3
3
  require 'locatine/version'
4
4
  require 'locatine/daemon'
5
+ require 'locatine/session'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: locatine
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.02637'
4
+ version: '0.02651'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sergei Seleznev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-11-18 00:00:00.000000000 Z
11
+ date: 2020-03-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -25,7 +25,7 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: rspec
28
+ name: pry
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
@@ -39,7 +39,7 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: simplecov
42
+ name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
@@ -53,7 +53,7 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: pry
56
+ name: simplecov
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
@@ -73,7 +73,7 @@ dependencies:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
75
  version: '6.16'
76
- type: :runtime
76
+ type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
@@ -90,7 +90,7 @@ dependencies:
90
90
  - - ">="
91
91
  - !ruby/object:Gem::Version
92
92
  version: 4.0.1
93
- type: :runtime
93
+ type: :development
94
94
  prerelease: false
95
95
  version_requirements: !ruby/object:Gem::Requirement
96
96
  requirements:
@@ -104,16 +104,30 @@ dependencies:
104
104
  name: sinatra
105
105
  requirement: !ruby/object:Gem::Requirement
106
106
  requirements:
107
- - - ">="
107
+ - - "~>"
108
108
  - !ruby/object:Gem::Version
109
- version: 2.0.5
109
+ version: '2.0'
110
110
  type: :runtime
111
111
  prerelease: false
112
112
  version_requirements: !ruby/object:Gem::Requirement
113
113
  requirements:
114
- - - ">="
114
+ - - "~>"
115
+ - !ruby/object:Gem::Version
116
+ version: '2.0'
117
+ - !ruby/object:Gem::Dependency
118
+ name: colorize
119
+ requirement: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - "~>"
122
+ - !ruby/object:Gem::Version
123
+ version: '0.8'
124
+ type: :runtime
125
+ prerelease: false
126
+ version_requirements: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - "~>"
115
129
  - !ruby/object:Gem::Version
116
- version: 2.0.5
130
+ version: '0.8'
117
131
  description: The main goal to write locators never
118
132
  email: s_seleznev_qa@hotmail.com
119
133
  executables:
@@ -124,43 +138,20 @@ files:
124
138
  - README.md
125
139
  - bin/locatine-daemon.rb
126
140
  - lib/locatine.rb
127
- - lib/locatine/app/background.js
128
- - lib/locatine/app/content.css
129
- - lib/locatine/app/content.js
130
- - lib/locatine/app/devtools.html
131
- - lib/locatine/app/devtools.js
132
- - lib/locatine/app/manifest.json
133
- - lib/locatine/app/popup.css
134
- - lib/locatine/app/popup.html
135
- - lib/locatine/app/popup.js
136
141
  - lib/locatine/daemon.rb
137
- - lib/locatine/daemon_helpers.rb
138
- - lib/locatine/for_search.rb
139
- - lib/locatine/for_search/data_generate.rb
140
- - lib/locatine/for_search/data_logic.rb
141
- - lib/locatine/for_search/defaults.rb
142
- - lib/locatine/for_search/dialog_logic.rb
143
- - lib/locatine/for_search/element_selection.rb
144
- - lib/locatine/for_search/file_work.rb
145
- - lib/locatine/for_search/find_by_guess.rb
146
- - lib/locatine/for_search/find_by_locator.rb
147
- - lib/locatine/for_search/find_by_magic.rb
148
- - lib/locatine/for_search/find_logic.rb
149
- - lib/locatine/for_search/helpers.rb
150
- - lib/locatine/for_search/highlight.rb
151
- - lib/locatine/for_search/listening.rb
152
- - lib/locatine/for_search/merge.rb
153
- - lib/locatine/for_search/name_helper.rb
154
- - lib/locatine/for_search/page_work.rb
155
- - lib/locatine/for_search/public.rb
156
- - lib/locatine/for_search/saying.rb
157
- - lib/locatine/for_search/xpath_generator.rb
158
- - lib/locatine/large_scripts/css.js
159
- - lib/locatine/large_scripts/dimensions.js
160
- - lib/locatine/large_scripts/element.js
161
- - lib/locatine/large_scripts/page.js
162
- - lib/locatine/scope.rb
163
- - lib/locatine/search.rb
142
+ - lib/locatine/daemon_helpers/methods.rb
143
+ - lib/locatine/element.rb
144
+ - lib/locatine/results.rb
145
+ - lib/locatine/results_helpers/common.rb
146
+ - lib/locatine/results_helpers/find_by_magic.rb
147
+ - lib/locatine/results_helpers/guess.rb
148
+ - lib/locatine/results_helpers/info_generator.rb
149
+ - lib/locatine/results_helpers/logger.rb
150
+ - lib/locatine/results_helpers/xpath_generator.rb
151
+ - lib/locatine/scripts/element.js
152
+ - lib/locatine/scripts/page.js
153
+ - lib/locatine/scripts/parent.js
154
+ - lib/locatine/session.rb
164
155
  - lib/locatine/version.rb
165
156
  homepage: https://github.com/sseleznevqa/locatine
166
157
  licenses:
@@ -181,8 +172,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
181
172
  - !ruby/object:Gem::Version
182
173
  version: '0'
183
174
  requirements: []
184
- rubyforge_project:
185
- rubygems_version: 2.5.2.3
175
+ rubygems_version: 3.0.3
186
176
  signing_key:
187
177
  specification_version: 4
188
178
  summary: Element locating tool based on watir
@@ -1,8 +0,0 @@
1
- chrome.browserAction.onClicked.addListener(
2
- function(tab) {
3
- chrome.windows.create( {'url': 'popup.html',
4
- 'type': 'popup',
5
- 'width': 640,
6
- 'height': 480});
7
-
8
- });
@@ -1,38 +0,0 @@
1
- @keyframes locatine_found {
2
- 0% {border: 4px dashed #6495ED;}
3
- 20% {border: 4px dashed #FF7F50;}
4
- 40% {border: 4px dashed #8FBC8F;}
5
- 60% {border: 4px dashed #FFA500;}
6
- 80% {border: 4px dashed #DDA0DD;}
7
- 100% {border: 4px dashed #6495ED;}
8
- }
9
-
10
- div[locatinestyle=true] {
11
- position:fixed;
12
- padding:0;
13
- margin:0;
14
- top:0;
15
- left:0;
16
- opacity: 0;
17
- background-color:rgba(0, 0, 0, 0.5);
18
- height: 100%;
19
- width: 100%;
20
- display: block;
21
- z-index: 2147483646;
22
- color: #FF99AA;
23
- font-size: 4vw;
24
- text-align: center;
25
- cursor: default;
26
- }
27
-
28
- div[locatinestyle=false] {
29
- height: 0%;
30
- width: 0%;
31
- }
32
-
33
- [locatineclass=foundbylocatine]
34
- {animation: locatine_found 6s infinite;
35
- -webkit-appearance: none;
36
- -moz-appearance: none;
37
- appearance: none;
38
- }