locatine 0.02637 → 0.03050

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +266 -297
  3. data/bin/locatine-daemon.rb +4 -2
  4. data/lib/locatine.rb +16 -2
  5. data/lib/locatine/daemon.rb +45 -59
  6. data/lib/locatine/daemon_helpers/methods.rb +93 -0
  7. data/lib/locatine/element.rb +46 -0
  8. data/lib/locatine/error.rb +14 -0
  9. data/lib/locatine/logger.rb +73 -0
  10. data/lib/locatine/results.rb +124 -0
  11. data/lib/locatine/results_helpers/common.rb +61 -0
  12. data/lib/locatine/results_helpers/comparing.rb +51 -0
  13. data/lib/locatine/results_helpers/config.rb +48 -0
  14. data/lib/locatine/results_helpers/find_by_magic.rb +123 -0
  15. data/lib/locatine/results_helpers/guess.rb +47 -0
  16. data/lib/locatine/results_helpers/info_generator.rb +77 -0
  17. data/lib/locatine/{for_search → results_helpers}/xpath_generator.rb +19 -18
  18. data/lib/locatine/scripts/element.js +40 -0
  19. data/lib/locatine/scripts/page.js +54 -0
  20. data/lib/locatine/scripts/parent.js +6 -0
  21. data/lib/locatine/session.rb +147 -0
  22. data/lib/locatine/version.rb +4 -2
  23. metadata +42 -49
  24. data/lib/locatine/app/background.js +0 -8
  25. data/lib/locatine/app/content.css +0 -38
  26. data/lib/locatine/app/content.js +0 -152
  27. data/lib/locatine/app/devtools.html +0 -1
  28. data/lib/locatine/app/devtools.js +0 -3
  29. data/lib/locatine/app/manifest.json +0 -20
  30. data/lib/locatine/app/popup.css +0 -47
  31. data/lib/locatine/app/popup.html +0 -19
  32. data/lib/locatine/app/popup.js +0 -65
  33. data/lib/locatine/daemon_helpers.rb +0 -52
  34. data/lib/locatine/for_search.rb +0 -6
  35. data/lib/locatine/for_search/data_generate.rb +0 -67
  36. data/lib/locatine/for_search/data_logic.rb +0 -98
  37. data/lib/locatine/for_search/defaults.rb +0 -40
  38. data/lib/locatine/for_search/dialog_logic.rb +0 -107
  39. data/lib/locatine/for_search/element_selection.rb +0 -80
  40. data/lib/locatine/for_search/file_work.rb +0 -67
  41. data/lib/locatine/for_search/find_by_guess.rb +0 -67
  42. data/lib/locatine/for_search/find_by_locator.rb +0 -59
  43. data/lib/locatine/for_search/find_by_magic.rb +0 -65
  44. data/lib/locatine/for_search/find_logic.rb +0 -79
  45. data/lib/locatine/for_search/helpers.rb +0 -106
  46. data/lib/locatine/for_search/highlight.rb +0 -41
  47. data/lib/locatine/for_search/listening.rb +0 -48
  48. data/lib/locatine/for_search/merge.rb +0 -40
  49. data/lib/locatine/for_search/name_helper.rb +0 -51
  50. data/lib/locatine/for_search/page_work.rb +0 -126
  51. data/lib/locatine/for_search/public.rb +0 -179
  52. data/lib/locatine/for_search/saying.rb +0 -199
  53. data/lib/locatine/large_scripts/css.js +0 -21
  54. data/lib/locatine/large_scripts/dimensions.js +0 -17
  55. data/lib/locatine/large_scripts/element.js +0 -30
  56. data/lib/locatine/large_scripts/page.js +0 -60
  57. data/lib/locatine/scope.rb +0 -88
  58. data/lib/locatine/search.rb +0 -67
@@ -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,54 @@
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
+ // We need to incapsulate since chromedriver cannot return a giant object
54
+ return JSON.stringify({"result": [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,147 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Locatine
4
+ ##
5
+ # Locatine Session class.
6
+ #
7
+ # Each selenium session gets a locatine session. Locatine session knows
8
+ # selenium address and session_id so it is able to communicate with selenium.
9
+ # It has no complex logic, but acts like a bridge between daemon and selenium
10
+ # while element is searched
11
+ class Session
12
+ include Locatine::Logger
13
+ attr_accessor :json, :depth, :trusted, :untrusted, :tolerance, :stability,
14
+ :elements, :timeout
15
+
16
+ ##
17
+ # Init of the new session instance
18
+ #
19
+ # +selenium+ is a selenium address like "https://host:port"
20
+ # +session+ is a session id provided by selenium
21
+ def initialize(selenium, session)
22
+ @selenium = selenium
23
+ @parsed_selenium = URI.parse @selenium
24
+ @session = session
25
+ @elements = []
26
+ @threads = []
27
+ # defaults
28
+ configure defaults
29
+ end
30
+
31
+ ##
32
+ # This method is to set settings
33
+ #
34
+ # +params+ is a hash of settings like {json: "some", depth: 0...}
35
+ def configure(params)
36
+ params.to_h.each_pair do |var, value|
37
+ instance_variable_set("@#{var}", value)
38
+ read if var.to_s == 'json'
39
+ end
40
+ params
41
+ end
42
+
43
+ ##
44
+ # Find method is for finding elements.
45
+ #
46
+ # That is the part that is replacing simple finding by selenium
47
+ # +params+ is a hash of settings like {json: "some", depth: 0...}
48
+ # +parent+ is an element code of the element to look under. It is counted
49
+ # only for the most simple search. If element is lost parent will be
50
+ # ignored
51
+ def find(params, parent = nil)
52
+ find_routine(params, parent)
53
+ rescue RuntimeError => e
54
+ raise e.message unless e.message == 'stale element reference'
55
+
56
+ warn_unstable_page
57
+ find(params, parent)
58
+ end
59
+
60
+ ##
61
+ # Session can execute js scripts on a page
62
+ #
63
+ # Note this method will be not called when you are asking selenoum via
64
+ # locatine to execute a script. This class is for internal use.
65
+ # +script+ some valid js code
66
+ # +*args+ arguments to be passed to script.
67
+ def execute_script(script, *args)
68
+ args.map! { |item| item.class == Locatine::Element ? item.answer : item }
69
+ response = api_request('/execute/sync', 'Post',
70
+ { script: script, args: args }.to_json).body
71
+ value = JSON.parse(response, max_nesting: false)['value']
72
+ error_present = (value.class == Hash) && value['error']
73
+ raise_script_error(script, args, value) if error_present
74
+
75
+ value
76
+ end
77
+
78
+ ##
79
+ # Returning information about the current page
80
+ def page
81
+ # We need duplicated JSON parse since standart
82
+ # chromedriver giving an error here if the page is too large
83
+ page = execute_script(File.read("#{HOME}/scripts/page.js"))
84
+ JSON.parse(page, max_nesting: false)['result']
85
+ end
86
+
87
+ ##
88
+ # This method is used to ask selenium about something.
89
+ #
90
+ # We are using it to ask for elements found by selenium or
91
+ # for script execution
92
+ # +path+ is a relative path to call on selenium like '/elements'
93
+ # +method+ is an http method to perform ('Get', 'Post', etc.)
94
+ # +body+ is for request data. json here (selenium wants it) or nil
95
+ def api_request(path, method, body)
96
+ uri = call_uri(path)
97
+ req = Net::HTTP.const_get(method)
98
+ .new(uri,
99
+ "Content-Type": 'application/json; charset=utf-8',
100
+ "Cache-Control": 'no-cache')
101
+ req.body = body
102
+ Net::HTTP.new(uri.hostname, uri.port).start { |http| http.request(req) }
103
+ end
104
+
105
+ private
106
+
107
+ def defaults
108
+ { json: "#{Dir.pwd}/locatine_files/default.json", depth: 3, trusted: [],
109
+ untrusted: [], tolerance: 50, stability: 10, timeout: 25 }
110
+ end
111
+
112
+ def read
113
+ dir = File.dirname(@json)
114
+ FileUtils.mkdir_p(dir) unless File.directory?(dir)
115
+ unless File.exist?(@json)
116
+ File.open(@json, 'w') do |f|
117
+ f.write('{"elements" : {}}')
118
+ end
119
+ end
120
+ @elements = JSON.parse(File.read(@json))['elements']
121
+ end
122
+
123
+ def write
124
+ File.open(@json, 'w') do |f|
125
+ f.write(JSON.pretty_generate('elements' => @elements))
126
+ end
127
+ end
128
+
129
+ def find_routine(params, parent)
130
+ results = Results.new
131
+ answer = results.find(self, params, parent)
132
+ if !answer.empty? && answer.first.class != Locatine::Error
133
+ @elements[results.name] = results.info
134
+ write
135
+ end
136
+ answer
137
+ end
138
+
139
+ def call_uri(path)
140
+ URI::HTTP.build(
141
+ host: @parsed_selenium.host,
142
+ port: @parsed_selenium.port,
143
+ path: "/wd/hub/session/#{@session}#{path}"
144
+ )
145
+ end
146
+ end
147
+ 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.03050'
6
+ NAME = 'locatine'
5
7
  HOME = if File.readable?("#{Dir.pwd}/lib/#{Locatine::NAME}")
6
8
  "#{Dir.pwd}/lib/#{Locatine::NAME}"
7
9
  else
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.03050'
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-10 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,23 @@ 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/error.rb
145
+ - lib/locatine/logger.rb
146
+ - lib/locatine/results.rb
147
+ - lib/locatine/results_helpers/common.rb
148
+ - lib/locatine/results_helpers/comparing.rb
149
+ - lib/locatine/results_helpers/config.rb
150
+ - lib/locatine/results_helpers/find_by_magic.rb
151
+ - lib/locatine/results_helpers/guess.rb
152
+ - lib/locatine/results_helpers/info_generator.rb
153
+ - lib/locatine/results_helpers/xpath_generator.rb
154
+ - lib/locatine/scripts/element.js
155
+ - lib/locatine/scripts/page.js
156
+ - lib/locatine/scripts/parent.js
157
+ - lib/locatine/session.rb
164
158
  - lib/locatine/version.rb
165
159
  homepage: https://github.com/sseleznevqa/locatine
166
160
  licenses:
@@ -181,8 +175,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
181
175
  - !ruby/object:Gem::Version
182
176
  version: '0'
183
177
  requirements: []
184
- rubyforge_project:
185
- rubygems_version: 2.5.2.3
178
+ rubygems_version: 3.0.3
186
179
  signing_key:
187
180
  specification_version: 4
188
181
  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
- }