superbot 0.1.4.rc2 → 0.1.4
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 +4 -4
- data/Gemfile +2 -0
- data/Gemfile.lock +3 -3
- data/lib/superbot.rb +17 -0
- data/lib/superbot/capybara/runner.rb +87 -9
- data/lib/superbot/cli/run_command.rb +20 -5
- data/lib/superbot/cli/validations.rb +8 -0
- data/lib/superbot/version.rb +1 -1
- data/lib/superbot/web.rb +67 -2
- data/superbot.gemspec +0 -1
- metadata +4 -24
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ee9ae1f83e72e26124dc00f1f322745f47ac8dade7a5f062db7f0e929f354b10
|
4
|
+
data.tar.gz: ff9aa3e5a57a52561232189a6b412b032585ded038e6f710e96b61fbe7b0e121
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4a7dae05cc2f2d1bf179d01f16e187c322bf3ddfd4fd6e05907db8891f5b8889bad510fb494dd78e51ca51ad92c2a54b41b879f5b8190e1b19d713443dc51c17
|
7
|
+
data.tar.gz: 68041c760b296560d8602814866ecce7a02c0ac233fac48878440be37a92da2c9c167d5a6ca3fd9c708336064c38731918d2cd96cba97eac96ac2bce9d91b28b
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
superbot (0.1.4
|
4
|
+
superbot (0.1.4)
|
5
5
|
clamp (= 1.2.1)
|
6
6
|
kommando (~> 0.1)
|
7
7
|
launchy (= 2.4.3)
|
@@ -69,7 +69,7 @@ GEM
|
|
69
69
|
mini_portile2 (2.3.0)
|
70
70
|
mustermann (1.0.3)
|
71
71
|
nenv (0.3.0)
|
72
|
-
nokogiri (1.8.
|
72
|
+
nokogiri (1.8.5)
|
73
73
|
mini_portile2 (~> 2.3.0)
|
74
74
|
notiffany (0.1.1)
|
75
75
|
nenv (~> 0.1)
|
@@ -142,7 +142,7 @@ GEM
|
|
142
142
|
thor (0.20.0)
|
143
143
|
tilt (2.0.8)
|
144
144
|
unicode-display_width (1.3.3)
|
145
|
-
xpath (3.
|
145
|
+
xpath (3.2.0)
|
146
146
|
nokogiri (~> 1.8)
|
147
147
|
zaru (0.2.0)
|
148
148
|
|
data/lib/superbot.rb
CHANGED
@@ -1,9 +1,26 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Superbot
|
4
|
+
WEBDRIVER_ENDPOINT = {
|
5
|
+
cloud: "http://bot1:hcegZRUvrfJJTSVT3KTDyggpEZAUSS@webdriver.superbot.cloud:3000/webdriver/v1",
|
6
|
+
local: "http://127.0.0.1:9515"
|
7
|
+
}.freeze
|
8
|
+
private_constant :WEBDRIVER_ENDPOINT
|
9
|
+
|
10
|
+
CLOUD_TIMEOUT = 2000
|
11
|
+
private_constant :CLOUD_TIMEOUT
|
12
|
+
|
4
13
|
def self.test_run?
|
5
14
|
ENV["SUPERBOT_TEST_RUN"] == "true"
|
6
15
|
end
|
16
|
+
|
17
|
+
def self.webdriver_endpoint(type)
|
18
|
+
WEBDRIVER_ENDPOINT[type.to_sym]
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.cloud_timeout
|
22
|
+
CLOUD_TIMEOUT
|
23
|
+
end
|
7
24
|
end
|
8
25
|
|
9
26
|
require_relative "superbot/version"
|
@@ -5,13 +5,26 @@ require 'kommando'
|
|
5
5
|
module Superbot
|
6
6
|
module Capybara
|
7
7
|
class Runner
|
8
|
-
def
|
9
|
-
|
8
|
+
def initialize(browser: :local, region: nil)
|
9
|
+
@browser = browser
|
10
|
+
@region = region
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.run(script, browser: :local, region: nil)
|
14
|
+
new(browser: browser, region: region).run(script)
|
10
15
|
end
|
11
16
|
|
12
17
|
def run(script)
|
18
|
+
puts "Attaching to #{browser} browser..."
|
13
19
|
create_runner
|
20
|
+
if browser == 'cloud'
|
21
|
+
puts "Opening screenshot stream..."
|
22
|
+
runner.in.writeln({ eval: screenshot_stream }.to_json)
|
23
|
+
wait_for_finish
|
24
|
+
end
|
25
|
+
puts "Running test..."
|
14
26
|
runner.in.writeln({ eval: script }.to_json)
|
27
|
+
wait_for_finish
|
15
28
|
end
|
16
29
|
|
17
30
|
def kill_session
|
@@ -22,39 +35,104 @@ module Superbot
|
|
22
35
|
@runner = nil
|
23
36
|
end
|
24
37
|
|
25
|
-
|
38
|
+
def wait_for_finish
|
39
|
+
loop do
|
40
|
+
if finished
|
41
|
+
@finished = false
|
42
|
+
break
|
43
|
+
end
|
44
|
+
|
45
|
+
sleep 0.1
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
attr_accessor :script, :runner, :finished, :test_result, :browser, :region
|
26
50
|
|
27
51
|
private
|
28
52
|
|
29
53
|
def create_runner
|
54
|
+
@finished = false
|
55
|
+
|
30
56
|
return if runner
|
31
57
|
|
32
58
|
gem 'superbot-capybara'
|
33
59
|
|
34
60
|
@runner = Kommando.new "sb-capybara"
|
35
61
|
|
36
|
-
@finished = false
|
37
|
-
|
38
62
|
runner.out.every(/{"type":"ok".*\n/) do
|
39
|
-
|
63
|
+
@test_result = "Test succeed!"
|
40
64
|
@finished = true
|
41
65
|
end
|
42
66
|
|
43
67
|
runner.out.every(/{"type":"error".*\n/) do
|
44
68
|
parsed_error = JSON.parse(runner.out.lines.last, symbolize_names: true)
|
45
|
-
|
69
|
+
@test_result = "Test failed: #{parsed_error[:message]}"
|
46
70
|
@finished = true
|
47
71
|
|
48
|
-
|
72
|
+
case parsed_error[:class]
|
73
|
+
when "Selenium::WebDriver::Error::WebDriverError", "Selenium::WebDriver::Error::NoSuchWindowError"
|
74
|
+
kill_session
|
75
|
+
puts parsed_error[:message]
|
76
|
+
puts "", "Seems like browser session has been closed, try to run test again to create new session"
|
77
|
+
when "Selenium::WebDriver::Error::ServerError"
|
49
78
|
kill_session
|
50
|
-
|
79
|
+
abort "Remote browser error: #{parsed_error[:message]}"
|
80
|
+
else
|
81
|
+
puts parsed_error[:message]
|
51
82
|
end
|
52
83
|
end
|
53
84
|
|
54
85
|
runner.run_async
|
86
|
+
|
87
|
+
runner.in.writeln({ eval: webdriver_config }.to_json)
|
88
|
+
wait_for_finish
|
55
89
|
rescue Gem::LoadError
|
56
90
|
abort "superbot-capybara not installed"
|
57
91
|
end
|
92
|
+
|
93
|
+
def webdriver_config
|
94
|
+
<<-WEBDRIVER_CONFIG
|
95
|
+
::Capybara.register_driver :chrome_remote do |app|
|
96
|
+
webdriver_capabilities = ::Selenium::WebDriver::Remote::Capabilities.chrome(
|
97
|
+
chromeOptions: {
|
98
|
+
'args' => [
|
99
|
+
'no-sandbox',
|
100
|
+
'no-default-browser-check',
|
101
|
+
'disable-infobars',
|
102
|
+
'app=about:blank',
|
103
|
+
]
|
104
|
+
},
|
105
|
+
superOptions: #{region ? { region: region } : {}}
|
106
|
+
)
|
107
|
+
|
108
|
+
webdriver_http_client = ::Selenium::WebDriver::Remote::Http::Default.new.tap do |client|
|
109
|
+
client.read_timeout = #{Superbot.cloud_timeout}
|
110
|
+
client.open_timeout = #{Superbot.cloud_timeout}
|
111
|
+
end
|
112
|
+
|
113
|
+
::Capybara::Selenium::Driver.new(
|
114
|
+
app,
|
115
|
+
browser: :chrome,
|
116
|
+
desired_capabilities: webdriver_capabilities,
|
117
|
+
http_client: webdriver_http_client,
|
118
|
+
url: 'http://127.0.0.1:4567/wd/hub'
|
119
|
+
)
|
120
|
+
end
|
121
|
+
::Capybara.current_driver = :chrome_remote
|
122
|
+
session_id = ::Capybara.current_session.driver.browser.send(:bridge).session_id
|
123
|
+
WEBDRIVER_CONFIG
|
124
|
+
end
|
125
|
+
|
126
|
+
def screenshot_stream
|
127
|
+
<<-SCREENSHOT_STREAM
|
128
|
+
screenshots_url = 'http://peek.superbot.cloud/v1/' + session_id
|
129
|
+
::Capybara.current_driver = :selenium_chrome
|
130
|
+
::Capybara.session_name = :peek
|
131
|
+
visit screenshots_url
|
132
|
+
::Capybara.current_driver = :chrome_remote
|
133
|
+
::Capybara.session_name = :default
|
134
|
+
SCREENSHOT_STREAM
|
135
|
+
end
|
58
136
|
end
|
59
137
|
end
|
60
138
|
end
|
@@ -7,18 +7,33 @@ module Superbot
|
|
7
7
|
|
8
8
|
parameter "PATH", "project directory" do |path|
|
9
9
|
validates_project_path path
|
10
|
+
end
|
10
11
|
|
11
|
-
|
12
|
+
option ['--browser'], 'BROWSER', "Browser type to use. Can be either local or cloud", default: 'local' do |browser|
|
13
|
+
validates_browser_type browser
|
12
14
|
end
|
15
|
+
option ['--region'], 'REGION', 'Region for remote webdriver'
|
13
16
|
|
14
17
|
def execute
|
15
|
-
|
16
|
-
web.run_async_after_running!
|
18
|
+
script = File.read(File.join(path, 'main.rb'))
|
17
19
|
|
20
|
+
webdriver_proxy = Superbot::Web.new(webdriver_endpoint: Superbot.webdriver_endpoint(browser))
|
21
|
+
webdriver_proxy.run_async_after_running!
|
18
22
|
puts "🤖 active"
|
19
|
-
|
20
|
-
|
23
|
+
|
24
|
+
chromedriver = Kommando.run_async 'chromedriver --silent --port=9515' if browser == 'local'
|
25
|
+
|
26
|
+
capybara_runner = Superbot::Capybara::Runner.new(browser: browser, region: region)
|
27
|
+
capybara_runner.run(script)
|
28
|
+
|
29
|
+
puts capybara_runner.test_result
|
30
|
+
puts "Press ENTER to exit"
|
31
|
+
|
21
32
|
$stdin.gets
|
33
|
+
ensure
|
34
|
+
chromedriver&.kill
|
35
|
+
webdriver_proxy&.quit!
|
36
|
+
capybara_runner&.kill_session
|
22
37
|
end
|
23
38
|
end
|
24
39
|
end
|
@@ -14,5 +14,13 @@ module Superbot
|
|
14
14
|
|
15
15
|
path
|
16
16
|
end
|
17
|
+
|
18
|
+
def validates_browser_type(browser)
|
19
|
+
unless %w(local cloud).include?(browser)
|
20
|
+
raise ArgumentError, "The '#{browser}' browser option is not allowed. Should be either 'local' or 'cloud'."
|
21
|
+
end
|
22
|
+
|
23
|
+
browser
|
24
|
+
end
|
17
25
|
end
|
18
26
|
end
|
data/lib/superbot/version.rb
CHANGED
data/lib/superbot/web.rb
CHANGED
@@ -1,13 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "sinatra/base"
|
4
4
|
require "sinatra/silent"
|
5
|
+
require 'net/http'
|
6
|
+
|
5
7
|
require_relative "capybara/convert"
|
6
8
|
require_relative "capybara/runner"
|
7
9
|
|
8
10
|
module Superbot
|
9
11
|
class Web
|
10
|
-
def initialize
|
12
|
+
def initialize(webdriver_endpoint: nil)
|
11
13
|
@sinatra = Sinatra.new
|
12
14
|
@sinatra.set :bind, "127.0.0.1"
|
13
15
|
@sinatra.set :silent_sinatra, true
|
@@ -34,12 +36,71 @@ module Superbot
|
|
34
36
|
converted_script = Superbot::Capybara::Convert.call(request.body.read)
|
35
37
|
instance.capybara_runner.run(converted_script)
|
36
38
|
end
|
39
|
+
|
40
|
+
return unless webdriver_endpoint
|
41
|
+
|
42
|
+
webdriver_uri = URI.parse(webdriver_endpoint)
|
43
|
+
@request_settings = {
|
44
|
+
userinfo: webdriver_uri.userinfo,
|
45
|
+
host: webdriver_uri.host,
|
46
|
+
port: webdriver_uri.port,
|
47
|
+
path: webdriver_uri.path
|
48
|
+
}
|
49
|
+
|
50
|
+
%w(get post put patch delete).each do |verb|
|
51
|
+
@sinatra.send(verb, "/wd/hub/*") do
|
52
|
+
begin
|
53
|
+
content_type 'application/json'
|
54
|
+
response = instance.remote_webdriver_request(
|
55
|
+
verb.capitalize,
|
56
|
+
request.path_info,
|
57
|
+
request.query_string,
|
58
|
+
request.body,
|
59
|
+
instance.incomming_headers(request)
|
60
|
+
)
|
61
|
+
status response.code
|
62
|
+
headers instance.all_headers(response)
|
63
|
+
response.body
|
64
|
+
rescue => e
|
65
|
+
puts e.message
|
66
|
+
halt 500, { message: e.message }.to_json
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
37
70
|
end
|
38
71
|
|
39
72
|
def capybara_runner
|
40
73
|
@capybara_runner ||= Superbot::Capybara::Runner.new
|
41
74
|
end
|
42
75
|
|
76
|
+
def remote_webdriver_request(type, path, query_string, body, new_headers)
|
77
|
+
uri = URI::HTTP.build(
|
78
|
+
@request_settings.merge(
|
79
|
+
path: [@request_settings[:path], path.gsub('wd/hub/', '')].join,
|
80
|
+
query: query_string.empty? ? nil : query_string
|
81
|
+
)
|
82
|
+
)
|
83
|
+
req = Net::HTTP.const_get(type).new(uri, new_headers.merge('Content-Type' => 'application/json'))
|
84
|
+
req.basic_auth(*@request_settings[:userinfo].split(':')) if @request_settings[:userinfo]
|
85
|
+
req.body = body.read
|
86
|
+
Net::HTTP.new(uri.hostname, uri.port).start do |http|
|
87
|
+
http.read_timeout = Superbot.cloud_timeout
|
88
|
+
http.request(req)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def all_headers(response)
|
93
|
+
header_list = {}
|
94
|
+
response.header.each_capitalized do |k, v|
|
95
|
+
header_list[k] = v unless k == "Transfer-Encoding"
|
96
|
+
end
|
97
|
+
header_list
|
98
|
+
end
|
99
|
+
|
100
|
+
def incomming_headers(request)
|
101
|
+
request.env.map { |header, value| [header[5..-1].split("_").map(&:capitalize).join('-'), value] if header.start_with?("HTTP_") }.compact.to_h
|
102
|
+
end
|
103
|
+
|
43
104
|
def run!
|
44
105
|
@sinatra.run_async!
|
45
106
|
end
|
@@ -55,5 +116,9 @@ module Superbot
|
|
55
116
|
sleep 0.001
|
56
117
|
end
|
57
118
|
end
|
119
|
+
|
120
|
+
def quit!
|
121
|
+
@sinatra&.quit!
|
122
|
+
end
|
58
123
|
end
|
59
124
|
end
|
data/superbot.gemspec
CHANGED
@@ -46,7 +46,6 @@ Gem::Specification.new do |spec|
|
|
46
46
|
spec.add_development_dependency "simplecov", "~> 0.16"
|
47
47
|
spec.add_development_dependency "parallel_tests", "~> 2.22"
|
48
48
|
spec.add_development_dependency "excon", "~> 0.62"
|
49
|
-
spec.add_development_dependency 'superbot-capybara', '~> 360.0', '>= 360.0.0'
|
50
49
|
|
51
50
|
spec.add_development_dependency "guard", "~> 2.14"
|
52
51
|
spec.add_development_dependency "guard-rspec", "~> 4.7"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: superbot
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.4
|
4
|
+
version: 0.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Superbots
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-10-
|
11
|
+
date: 2018-10-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: clamp
|
@@ -192,26 +192,6 @@ dependencies:
|
|
192
192
|
- - "~>"
|
193
193
|
- !ruby/object:Gem::Version
|
194
194
|
version: '0.62'
|
195
|
-
- !ruby/object:Gem::Dependency
|
196
|
-
name: superbot-capybara
|
197
|
-
requirement: !ruby/object:Gem::Requirement
|
198
|
-
requirements:
|
199
|
-
- - "~>"
|
200
|
-
- !ruby/object:Gem::Version
|
201
|
-
version: '360.0'
|
202
|
-
- - ">="
|
203
|
-
- !ruby/object:Gem::Version
|
204
|
-
version: 360.0.0
|
205
|
-
type: :development
|
206
|
-
prerelease: false
|
207
|
-
version_requirements: !ruby/object:Gem::Requirement
|
208
|
-
requirements:
|
209
|
-
- - "~>"
|
210
|
-
- !ruby/object:Gem::Version
|
211
|
-
version: '360.0'
|
212
|
-
- - ">="
|
213
|
-
- !ruby/object:Gem::Version
|
214
|
-
version: 360.0.0
|
215
195
|
- !ruby/object:Gem::Dependency
|
216
196
|
name: guard
|
217
197
|
requirement: !ruby/object:Gem::Requirement
|
@@ -308,9 +288,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
308
288
|
version: '0'
|
309
289
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
310
290
|
requirements:
|
311
|
-
- - "
|
291
|
+
- - ">="
|
312
292
|
- !ruby/object:Gem::Version
|
313
|
-
version:
|
293
|
+
version: '0'
|
314
294
|
requirements: []
|
315
295
|
rubyforge_project:
|
316
296
|
rubygems_version: 2.7.6
|