locatine 0.02327 → 0.02432
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +129 -1
- data/bin/locatine-daemon.rb +8 -0
- data/lib/locatine/app/manifest.json +1 -1
- data/lib/locatine/daemon.rb +93 -0
- data/lib/locatine/daemon_helpers.rb +52 -0
- data/lib/locatine/for_search/defaults.rb +45 -0
- data/lib/locatine/for_search/file_work.rb +0 -7
- data/lib/locatine/for_search/helpers.rb +0 -9
- data/lib/locatine/for_search/public.rb +23 -22
- data/lib/locatine/for_search/xpath_generator.rb +1 -1
- data/lib/locatine/search.rb +2 -0
- data/lib/locatine/version.rb +1 -1
- data/lib/locatine.rb +1 -0
- metadata +26 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2938862d7ec4f9e5db28711a7f40764d1911ea73
|
4
|
+
data.tar.gz: e6a0775a26dd2d7bd5516a8b0b198a6f4d4f7097
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 131784b53b1c62a289587e7c7fc8faf44abce5d5121ecbd08aa6c58a2bfce1bdd05712d31aa9e2e3cafc3f76d4a390728c41a96da0635ad1b4ae44573737a858
|
7
|
+
data.tar.gz: 0c80e987bb31e5991dc917849b4069d727f6f4902688e975a03c9248f6823e827b59545f0ed59e49b78dcd400f501d097db064ee51a87a518a07532628173e29
|
data/README.md
CHANGED
@@ -16,7 +16,7 @@ That's it.
|
|
16
16
|
|
17
17
|
## Stage of development:
|
18
18
|
|
19
|
-
Version of Locatine is **0.
|
19
|
+
Version of Locatine is **0.02432** only. It means so far this is an alfa. You can use it in a real project if you are a risky person.
|
20
20
|
|
21
21
|
## Installation
|
22
22
|
|
@@ -361,3 +361,131 @@ s.exact(name: "something") == s.find(name: "something", exact: true)
|
|
361
361
|
s.check(name: "something") == s.find(name: "something", tolerance: 0)
|
362
362
|
s.check_collection(name: "something") == s.collect(name: "something", tolerance: 0)
|
363
363
|
```
|
364
|
+
|
365
|
+
## Using as a daemon
|
366
|
+
|
367
|
+
Locatine daemon is a web server based on sinatra. You can run it from your code like:
|
368
|
+
|
369
|
+
```ruby
|
370
|
+
require 'locatine'
|
371
|
+
Locatine::Daemon.set :port, 7733 #Your port goes here
|
372
|
+
Locatine::Daemon.run!
|
373
|
+
```
|
374
|
+
|
375
|
+
Also you can do it with terminal:
|
376
|
+
|
377
|
+
```bash
|
378
|
+
locatine-daemon.rb -port=7733
|
379
|
+
```
|
380
|
+
|
381
|
+
You can see a python3 example in the [example](https://github.com/sseleznevqa/locatine/tree/master/example) folder. Main idea is
|
382
|
+
|
383
|
+
1. Run daemon
|
384
|
+
2. Ask daemon for the app path
|
385
|
+
3. Run your browser with the app as extension
|
386
|
+
4. Turn on the learn
|
387
|
+
5. Provide data to the daemon for connect (browser name, session_id, connect url, proxy)
|
388
|
+
6. Use API calls to teach daemon how to find elements
|
389
|
+
7. After that you can start browser without the app
|
390
|
+
8. Provide data for connect
|
391
|
+
9. Now you can ask daemon to find your element via API call. And it will answer with a valid xpath you can use.
|
392
|
+
|
393
|
+
### API
|
394
|
+
|
395
|
+
#### GET call to /app
|
396
|
+
|
397
|
+
returns path to locatine application in order to start chrome with it.
|
398
|
+
|
399
|
+
Example of response:
|
400
|
+
|
401
|
+
```
|
402
|
+
{"app": "/some/path/to/app"}
|
403
|
+
```
|
404
|
+
|
405
|
+
#### GET call to /stop
|
406
|
+
|
407
|
+
stops Locatine daemon.
|
408
|
+
|
409
|
+
Returns:
|
410
|
+
|
411
|
+
```
|
412
|
+
{"result": "dead"}
|
413
|
+
```
|
414
|
+
|
415
|
+
#### POST call to /connect
|
416
|
+
|
417
|
+
allows Locatine Daemon to connect existing browser instance
|
418
|
+
|
419
|
+
POST data:
|
420
|
+
|
421
|
+
```
|
422
|
+
{'browser': 'chrome', 'session_id': session_id, 'url': 'http://whatever_is_browser_ip:port_opened_by_browser_for_selenium', 'proxy': 'optionally' }
|
423
|
+
```
|
424
|
+
|
425
|
+
Answer:
|
426
|
+
|
427
|
+
```
|
428
|
+
{"result": "true"}
|
429
|
+
```
|
430
|
+
|
431
|
+
#### POST call to /set
|
432
|
+
|
433
|
+
is to control options of locatine search. Sending to set data ==
|
434
|
+
|
435
|
+
```
|
436
|
+
{"learn": "true"}
|
437
|
+
```
|
438
|
+
|
439
|
+
Answer:
|
440
|
+
|
441
|
+
```
|
442
|
+
{"result": "true"}
|
443
|
+
```
|
444
|
+
|
445
|
+
is the same as
|
446
|
+
|
447
|
+
```ruby
|
448
|
+
search.learn = true
|
449
|
+
```
|
450
|
+
|
451
|
+
#### POST call to /lctr
|
452
|
+
|
453
|
+
is to find and return locator of an element found by locatine
|
454
|
+
|
455
|
+
POST data just the same as for find or lctr method. It's like:
|
456
|
+
|
457
|
+
```
|
458
|
+
{"name": "some name", "scope": "Default", "exact": "false" ...}
|
459
|
+
```
|
460
|
+
|
461
|
+
Answer:
|
462
|
+
|
463
|
+
```
|
464
|
+
{"xpath": "//YOUR[@xpath='goes here']"}
|
465
|
+
```
|
466
|
+
|
467
|
+
### GET /chromedriver || /geckodriver || /iedriver
|
468
|
+
|
469
|
+
returns path to the binary retrieved by locatine (using webdrivers gem)
|
470
|
+
|
471
|
+
Answer:
|
472
|
+
|
473
|
+
```
|
474
|
+
{"path": "path/to/the/binary"}
|
475
|
+
```
|
476
|
+
|
477
|
+
### POST call to /chromedriver || /geckodriver || /iedriver
|
478
|
+
|
479
|
+
is to force locatine to use your webdriver (for example for using old version of browser)
|
480
|
+
|
481
|
+
POST data:
|
482
|
+
|
483
|
+
```
|
484
|
+
{"version": "2.46"}
|
485
|
+
```
|
486
|
+
|
487
|
+
Answer:
|
488
|
+
|
489
|
+
```
|
490
|
+
{"version": "2.46"}
|
491
|
+
```
|
@@ -0,0 +1,8 @@
|
|
1
|
+
#!Locatine-daemon...
|
2
|
+
require 'locatine'
|
3
|
+
args = Hash[ ARGV.join(' ').scan(/--?([^=\s]+)(?:=(\S+))?/) ]
|
4
|
+
args = args.inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo}
|
5
|
+
args.each_pair do |key, value|
|
6
|
+
Locatine::Daemon.set key, value
|
7
|
+
end
|
8
|
+
Locatine::Daemon.run!
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
require 'json'
|
3
|
+
require 'locatine/daemon_helpers'
|
4
|
+
|
5
|
+
module Locatine
|
6
|
+
#
|
7
|
+
# Locatine daemon based on sinatra
|
8
|
+
#
|
9
|
+
# run Locatine::Daemon.run!
|
10
|
+
class Daemon < Sinatra::Base
|
11
|
+
include Locatine::DaemonHelpers
|
12
|
+
configure do
|
13
|
+
set :search, nil
|
14
|
+
end
|
15
|
+
|
16
|
+
get '/app' do
|
17
|
+
{ app: File.join(Locatine::HOME, 'app').to_s }.to_json
|
18
|
+
end
|
19
|
+
|
20
|
+
get '/' do
|
21
|
+
redirect 'https://github.com/sseleznevqa/locatine#using-as-a-daemon'
|
22
|
+
end
|
23
|
+
|
24
|
+
get '/stop' do
|
25
|
+
Locatine::Daemon.quit!
|
26
|
+
{ result: 'dead' }.to_json
|
27
|
+
end
|
28
|
+
|
29
|
+
post '/chromedriver' do
|
30
|
+
Webdrivers::Chromedriver.required_version = params['version']
|
31
|
+
{ version: Webdrivers::Chromedriver.required_version }.to_json
|
32
|
+
end
|
33
|
+
|
34
|
+
get '/chromedriver' do
|
35
|
+
{ path: Webdrivers::Chromedriver.update }.to_json
|
36
|
+
end
|
37
|
+
|
38
|
+
post '/geckodriver' do
|
39
|
+
Webdrivers::Geckodriver.required_version = params['version']
|
40
|
+
{ version: Webdrivers::Geckodriver.required_version }.to_json
|
41
|
+
end
|
42
|
+
|
43
|
+
get '/geckodriver' do
|
44
|
+
{ path: Webdrivers::Geckodriver.update }.to_json
|
45
|
+
end
|
46
|
+
|
47
|
+
post 'iedriver' do
|
48
|
+
Webdrivers::IEdriver.required_version = params['version']
|
49
|
+
{ version: Webdrivers::IEdriver.required_version }.to_json
|
50
|
+
end
|
51
|
+
|
52
|
+
get '/iedriver' do
|
53
|
+
{ path: Webdrivers::IEdriver.update }.to_json
|
54
|
+
end
|
55
|
+
|
56
|
+
post '/connect' do
|
57
|
+
steal
|
58
|
+
{ result: true }.to_json
|
59
|
+
end
|
60
|
+
|
61
|
+
post '/lctr' do
|
62
|
+
data = Hash[params.map { |k, v| [k.to_sym, v] }]
|
63
|
+
data.each { |k, v| data[k] = false if v == 'false' }
|
64
|
+
search.lctr(data).to_json
|
65
|
+
end
|
66
|
+
|
67
|
+
post '/set' do
|
68
|
+
hash = params
|
69
|
+
search.json = hash['json'] if hash['json']
|
70
|
+
warn 'You cannot set browser like this. Use /connect' if hash['browser']
|
71
|
+
params.each_pair do |key, value|
|
72
|
+
unless (key == 'browser') || (key == 'json')
|
73
|
+
value = false if value == 'false'
|
74
|
+
search.instance_variable_set("@#{key}", value)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
{ result: true }.to_json
|
78
|
+
end
|
79
|
+
|
80
|
+
def search
|
81
|
+
return settings.search unless settings.search.nil?
|
82
|
+
|
83
|
+
settings.search = Locatine::Search.new
|
84
|
+
settings.search.browser.quit
|
85
|
+
settings.search
|
86
|
+
end
|
87
|
+
|
88
|
+
def params
|
89
|
+
request.body.rewind
|
90
|
+
JSON.parse request.body.read
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Locatine
|
2
|
+
#
|
3
|
+
# Usefull things daemon can do
|
4
|
+
module DaemonHelpers
|
5
|
+
private
|
6
|
+
|
7
|
+
def steal
|
8
|
+
cast_ghost_browser
|
9
|
+
disguise_session
|
10
|
+
disguise_server_url
|
11
|
+
disguise_http
|
12
|
+
disguise_proxy unless params['proxy'].to_s.empty?
|
13
|
+
end
|
14
|
+
|
15
|
+
def bridge
|
16
|
+
search.browser.wd.send(:bridge)
|
17
|
+
end
|
18
|
+
|
19
|
+
def b_http
|
20
|
+
bridge.send(:http)
|
21
|
+
end
|
22
|
+
|
23
|
+
def disguise_session
|
24
|
+
bridge.instance_variable_set('@session_id', params['session_id'])
|
25
|
+
end
|
26
|
+
|
27
|
+
def disguise_server_url
|
28
|
+
uri = URI.parse(params['url'])
|
29
|
+
b_http.instance_variable_set('@server_url', uri)
|
30
|
+
end
|
31
|
+
|
32
|
+
def disguise_http
|
33
|
+
b_http.instance_variable_set('@http', make_net)
|
34
|
+
end
|
35
|
+
|
36
|
+
def disguise_proxy
|
37
|
+
b_http.instance_variable_set('@proxy', params['proxy'])
|
38
|
+
end
|
39
|
+
|
40
|
+
def make_net
|
41
|
+
parsed = URI.parse(params['url'])
|
42
|
+
path = parsed.path == '/' ? '' : parsed.path
|
43
|
+
Net::HTTP.new("#{parsed.host}#{path}", parsed.port)
|
44
|
+
end
|
45
|
+
|
46
|
+
def cast_ghost_browser
|
47
|
+
search.browser = Watir::Browser.new(params['browser'].to_sym)
|
48
|
+
search.browser.quit
|
49
|
+
search.browser.instance_variable_set('@closed', false)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Locatine
|
2
|
+
module ForSearch
|
3
|
+
##
|
4
|
+
# Default settings for search are living here
|
5
|
+
module Defaults
|
6
|
+
private
|
7
|
+
def default_init_config
|
8
|
+
{ json: './Locatine_files/default.json',
|
9
|
+
depth: 3,
|
10
|
+
browser: nil,
|
11
|
+
learn: ENV['LEARN'].nil? ? false : true,
|
12
|
+
stability_limit: 1000,
|
13
|
+
scope: 'Default',
|
14
|
+
tolerance: 67,
|
15
|
+
visual_search: false,
|
16
|
+
no_fail: false,
|
17
|
+
trusted: [],
|
18
|
+
untrusted: []
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
def import_browser(browser)
|
23
|
+
selenium = browser.class.superclass == Selenium::WebDriver::Driver
|
24
|
+
b = right_browser unless browser
|
25
|
+
b = browser if browser.class == Watir::Browser
|
26
|
+
b = Watir::Browser.new(browser) if selenium
|
27
|
+
@browser = b
|
28
|
+
@default_styles = default_styles.to_a
|
29
|
+
end
|
30
|
+
|
31
|
+
def import_file(json)
|
32
|
+
@json = json
|
33
|
+
@folder = File.dirname(@json)
|
34
|
+
@name = File.basename(@json)
|
35
|
+
@data = read_create
|
36
|
+
end
|
37
|
+
|
38
|
+
def import_config(config)
|
39
|
+
config.each_pair do |key, value|
|
40
|
+
self.instance_variable_set("@#{key.to_s}", value)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -17,13 +17,6 @@ module Locatine
|
|
17
17
|
hash.merge(JSON.parse(File.read(@json))['data'])
|
18
18
|
end
|
19
19
|
|
20
|
-
def import_file(json)
|
21
|
-
@json = json
|
22
|
-
@folder = File.dirname(@json)
|
23
|
-
@name = File.basename(@json)
|
24
|
-
@data = read_create
|
25
|
-
end
|
26
|
-
|
27
20
|
def create_json_file
|
28
21
|
f = File.new(@json, 'w')
|
29
22
|
f.puts '{"data" : {}}'
|
@@ -64,15 +64,6 @@ module Locatine
|
|
64
64
|
Watir::Browser.new(:chrome, switches: ["--load-extension=#{HOME}/app"])
|
65
65
|
end
|
66
66
|
|
67
|
-
def import_browser(browser)
|
68
|
-
selenium = browser.class.superclass == Selenium::WebDriver::Driver
|
69
|
-
b = right_browser unless browser
|
70
|
-
b = browser if browser.class == Watir::Browser
|
71
|
-
b = Watir::Browser.new(browser) if selenium
|
72
|
-
@browser = b
|
73
|
-
@default_styles = default_styles.to_a
|
74
|
-
end
|
75
|
-
|
76
67
|
def css_text_to_hash(text)
|
77
68
|
almost_hash = []
|
78
69
|
array = text[0..-2].split('; ')
|
@@ -28,28 +28,21 @@ module Locatine
|
|
28
28
|
# to the lost one. Default is 67 which means that if less than 33% of
|
29
29
|
# metrics of alternative elements are the same as of the lost element
|
30
30
|
# will not be returned
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
@stability_limit = stability_limit
|
47
|
-
@scope = scope
|
48
|
-
@tolerance = tolerance
|
49
|
-
@visual_search = visual_search
|
50
|
-
@no_fail = no_fail
|
51
|
-
@trusted = trusted
|
52
|
-
@untrusted = untrusted
|
31
|
+
#
|
32
|
+
# +visual_search+ locatine will use position and style if true
|
33
|
+
#
|
34
|
+
# +no_fail+ if true locatine is not producing errors on element loss.
|
35
|
+
#
|
36
|
+
# +trusted+ array of names of attributes and element params to use
|
37
|
+
# in search always.
|
38
|
+
#
|
39
|
+
# +untrusted+ array of names of attributes and element params to use
|
40
|
+
# in search never.
|
41
|
+
def initialize(config = {})
|
42
|
+
init_config = default_init_config.merge(config)
|
43
|
+
import_browser init_config.delete :browser
|
44
|
+
import_file init_config.delete :json
|
45
|
+
import_config init_config
|
53
46
|
end
|
54
47
|
|
55
48
|
##
|
@@ -84,6 +77,14 @@ module Locatine
|
|
84
77
|
#
|
85
78
|
# +tolerance+ It is possible to set a custom tolerance for every find. See
|
86
79
|
# examples in README
|
80
|
+
#
|
81
|
+
# +no_fail+ if true locatine is not producing errors on element loss.
|
82
|
+
#
|
83
|
+
# +trusted+ array of names of attributes and element params to use
|
84
|
+
# in search always.
|
85
|
+
#
|
86
|
+
# +untrusted+ array of names of attributes and element params to use
|
87
|
+
# in search never.
|
87
88
|
def find(simple_name = nil,
|
88
89
|
name: nil,
|
89
90
|
scope: nil,
|
data/lib/locatine/search.rb
CHANGED
@@ -8,6 +8,7 @@ require 'locatine/for_search/merge'
|
|
8
8
|
require 'locatine/for_search/public'
|
9
9
|
require 'locatine/for_search/saying'
|
10
10
|
require 'locatine/for_search/helpers'
|
11
|
+
require 'locatine/for_search/defaults'
|
11
12
|
require 'locatine/for_search/file_work'
|
12
13
|
require 'locatine/for_search/listening'
|
13
14
|
require 'locatine/for_search/highlight'
|
@@ -33,6 +34,7 @@ module Locatine
|
|
33
34
|
include Locatine::ForSearch::Public
|
34
35
|
include Locatine::ForSearch::Saying
|
35
36
|
include Locatine::ForSearch::Helpers
|
37
|
+
include Locatine::ForSearch::Defaults
|
36
38
|
include Locatine::ForSearch::FileWork
|
37
39
|
include Locatine::ForSearch::DataLogic
|
38
40
|
include Locatine::ForSearch::Listening
|
data/lib/locatine/version.rb
CHANGED
data/lib/locatine.rb
CHANGED
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.
|
4
|
+
version: '0.02432'
|
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
|
+
date: 2019-06-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -100,27 +100,43 @@ dependencies:
|
|
100
100
|
requirements:
|
101
101
|
- - "~>"
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version: '
|
103
|
+
version: '4.0'
|
104
104
|
- - ">="
|
105
105
|
- !ruby/object:Gem::Version
|
106
|
-
version:
|
106
|
+
version: 4.0.1
|
107
107
|
type: :runtime
|
108
108
|
prerelease: false
|
109
109
|
version_requirements: !ruby/object:Gem::Requirement
|
110
110
|
requirements:
|
111
111
|
- - "~>"
|
112
112
|
- !ruby/object:Gem::Version
|
113
|
-
version: '
|
113
|
+
version: '4.0'
|
114
114
|
- - ">="
|
115
115
|
- !ruby/object:Gem::Version
|
116
|
-
version:
|
116
|
+
version: 4.0.1
|
117
|
+
- !ruby/object:Gem::Dependency
|
118
|
+
name: sinatra
|
119
|
+
requirement: !ruby/object:Gem::Requirement
|
120
|
+
requirements:
|
121
|
+
- - ">="
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: 2.0.5
|
124
|
+
type: :runtime
|
125
|
+
prerelease: false
|
126
|
+
version_requirements: !ruby/object:Gem::Requirement
|
127
|
+
requirements:
|
128
|
+
- - ">="
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
version: 2.0.5
|
117
131
|
description: The main goal to write locators never
|
118
132
|
email: s_seleznev_qa@hotmail.com
|
119
|
-
executables:
|
133
|
+
executables:
|
134
|
+
- locatine-daemon.rb
|
120
135
|
extensions: []
|
121
136
|
extra_rdoc_files: []
|
122
137
|
files:
|
123
138
|
- README.md
|
139
|
+
- bin/locatine-daemon.rb
|
124
140
|
- lib/locatine.rb
|
125
141
|
- lib/locatine/app/background.js
|
126
142
|
- lib/locatine/app/content.css
|
@@ -131,9 +147,12 @@ files:
|
|
131
147
|
- lib/locatine/app/popup.css
|
132
148
|
- lib/locatine/app/popup.html
|
133
149
|
- lib/locatine/app/popup.js
|
150
|
+
- lib/locatine/daemon.rb
|
151
|
+
- lib/locatine/daemon_helpers.rb
|
134
152
|
- lib/locatine/for_search.rb
|
135
153
|
- lib/locatine/for_search/data_generate.rb
|
136
154
|
- lib/locatine/for_search/data_logic.rb
|
155
|
+
- lib/locatine/for_search/defaults.rb
|
137
156
|
- lib/locatine/for_search/dialog_logic.rb
|
138
157
|
- lib/locatine/for_search/element_selection.rb
|
139
158
|
- lib/locatine/for_search/file_work.rb
|