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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1641f7b484bb325fb0f42f9e9b8edd5772ca03c6668190d15aad7f8d050a5b2e
4
- data.tar.gz: a98fda3df485173a91af53d806b1bc25886318acd3325d131b9b55283a160bf3
3
+ metadata.gz: ee9ae1f83e72e26124dc00f1f322745f47ac8dade7a5f062db7f0e929f354b10
4
+ data.tar.gz: ff9aa3e5a57a52561232189a6b412b032585ded038e6f710e96b61fbe7b0e121
5
5
  SHA512:
6
- metadata.gz: b67811f1460990d60c78e0e82b1c5da32ddec164227ea2a8d0acd6bec9bb241cf8a41254abfbe57ed743e019515a07ef88ea26d459fbf12a73f2ca5a2f6d1119
7
- data.tar.gz: 9ac5fc57b351326bb58f6e990a1893d109c89af894fb792698b090b15a070b80a97da3473700fd65eeb6f4dbf75205cd13f906d04691e8ec0cd4580032c63008
6
+ metadata.gz: 4a7dae05cc2f2d1bf179d01f16e187c322bf3ddfd4fd6e05907db8891f5b8889bad510fb494dd78e51ca51ad92c2a54b41b879f5b8190e1b19d713443dc51c17
7
+ data.tar.gz: 68041c760b296560d8602814866ecce7a02c0ac233fac48878440be37a92da2c9c167d5a6ca3fd9c708336064c38731918d2cd96cba97eac96ac2bce9d91b28b
data/Gemfile CHANGED
@@ -4,3 +4,5 @@ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
4
 
5
5
  # Specify your gem's dependencies in superbot.gemspec
6
6
  gemspec
7
+
8
+ gem "superbot-capybara", "~> 360.0", ">= 360.0.0"
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- superbot (0.1.4.rc2)
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.4)
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.1.0)
145
+ xpath (3.2.0)
146
146
  nokogiri (~> 1.8)
147
147
  zaru (0.2.0)
148
148
 
@@ -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 self.run(script)
9
- new.run(script)
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
- attr_accessor :script, :runner, :finished
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
- puts "Test succeed!"
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
- puts "Test failed: #{parsed_error[:message]}"
69
+ @test_result = "Test failed: #{parsed_error[:message]}"
46
70
  @finished = true
47
71
 
48
- if parsed_error[:class].match?(/Selenium::WebDriver::Error::(WebDriverError|NoSuchWindowError)/)
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
- puts "", "ERROR: Seems like browser session has been closed, try to run test again to create new session"
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
- path
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
- web = Superbot::Web.new
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
- puts ""
20
- puts "Press enter to exit"
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Superbot
4
- VERSION = "0.1.4.rc2"
4
+ VERSION = "0.1.4"
5
5
  end
@@ -1,13 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'sinatra'
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
@@ -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.rc2
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-19 00:00:00.000000000 Z
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: 1.3.1
293
+ version: '0'
314
294
  requirements: []
315
295
  rubyforge_project:
316
296
  rubygems_version: 2.7.6