superbot 0.1.4.rc2 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
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