selenium-connect 2.3.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. data/.coveralls.yml +1 -0
  2. data/.gitignore +1 -0
  3. data/.rspec +6 -0
  4. data/.travis.yml +1 -0
  5. data/CHANGELOG.md +16 -0
  6. data/Guardfile +6 -0
  7. data/README.md +121 -16
  8. data/Rakefile +36 -12
  9. data/lib/selenium-connect.rb +3 -82
  10. data/lib/selenium_connect.rb +49 -0
  11. data/lib/{selenium-connect → selenium_connect}/configuration.rb +4 -2
  12. data/lib/selenium_connect/job.rb +102 -0
  13. data/lib/selenium_connect/report/job_report.rb +17 -0
  14. data/lib/selenium_connect/report/main_report.rb +17 -0
  15. data/lib/selenium_connect/report/report_factory.rb +25 -0
  16. data/lib/{selenium-connect → selenium_connect}/runner.rb +9 -8
  17. data/lib/{selenium-connect → selenium_connect}/runners/chrome.rb +1 -1
  18. data/lib/{selenium-connect → selenium_connect}/runners/firefox.rb +1 -1
  19. data/lib/{selenium-connect → selenium_connect}/runners/ie.rb +1 -1
  20. data/lib/{selenium-connect → selenium_connect}/runners/no_browser.rb +1 -1
  21. data/lib/{selenium-connect → selenium_connect}/runners/phantomjs.rb +1 -1
  22. data/lib/{selenium-connect → selenium_connect}/runners/saucelabs.rb +2 -1
  23. data/lib/{selenium-connect → selenium_connect}/server.rb +2 -1
  24. data/selenium-connect.gemspec +9 -4
  25. data/spec/integration/lib/selenium_connect/runners/chrome_spec.rb +19 -0
  26. data/spec/integration/lib/selenium_connect/runners/firefox_spec.rb +55 -0
  27. data/spec/integration/lib/selenium_connect/runners/headless_spec.rb +33 -0
  28. data/spec/integration/lib/selenium_connect/runners/ie_spec.rb +24 -0
  29. data/spec/{runners → integration/lib/selenium_connect/runners}/phantomjs_spec.rb +4 -3
  30. data/spec/integration/lib/selenium_connect/runners/sauce_spec.rb +63 -0
  31. data/spec/integration/lib/selenium_connect_spec.rb +41 -0
  32. data/spec/spec_helper.rb +37 -0
  33. data/spec/{example.yaml → support/example.yaml} +0 -0
  34. data/spec/{acceptance/helper.rb → support/example_page_object.rb} +1 -1
  35. data/spec/support/integration_helper.rb +9 -0
  36. data/spec/unit/lib/selenium-connect_spec.rb +15 -0
  37. data/spec/{configuration_spec.rb → unit/lib/selenium_connect/configuration_spec.rb} +9 -3
  38. data/spec/unit/lib/selenium_connect/job_spec.rb +38 -0
  39. data/spec/unit/lib/selenium_connect/report/job_report_spec.rb +20 -0
  40. data/spec/unit/lib/selenium_connect/report/main_report_spec.rb +20 -0
  41. data/spec/unit/lib/selenium_connect/report/report_factory_spec.rb +27 -0
  42. data/spec/unit/lib/selenium_connect/runners/.gitkeep +0 -0
  43. data/spec/unit/lib/selenium_connect_spec.rb +58 -0
  44. metadata +125 -29
  45. data/spec/acceptance/chrome_spec.rb +0 -21
  46. data/spec/acceptance/firefox_spec.rb +0 -62
  47. data/spec/acceptance/headless_spec.rb +0 -29
  48. data/spec/acceptance/ie_spec.rb +0 -21
  49. data/spec/acceptance/logging_spec.rb +0 -28
  50. data/spec/acceptance/sauce_spec.rb +0 -27
  51. data/spec/quit_and_finish_spec.rb +0 -14
  52. data/spec/yaml_spec.rb +0 -51
@@ -2,7 +2,8 @@
2
2
 
3
3
  require 'yaml'
4
4
 
5
- module SeleniumConnect
5
+ # selenium connect
6
+ class SeleniumConnect
6
7
  # Encapsulates the configuration
7
8
  class Configuration
8
9
 
@@ -18,10 +19,11 @@ module SeleniumConnect
18
19
  attr_accessor :sauce_username, :sauce_api_key,
19
20
  :os, :browser_version, :description
20
21
 
21
- def initialize
22
+ def initialize(opts = {})
22
23
  @host = 'localhost'
23
24
  @port = 4444
24
25
  @browser = 'firefox'
26
+ populate_with_hash opts unless opts.empty?
25
27
  end
26
28
 
27
29
  def populate_with_hash(hash)
@@ -0,0 +1,102 @@
1
+ # Encoding: utf-8
2
+ require 'selenium_connect/runner'
3
+ require 'sauce/client'
4
+ require 'rest_client'
5
+ require 'selenium-webdriver'
6
+ require 'json'
7
+ require 'sauce_whisk'
8
+ require 'curb'
9
+
10
+ # selenium connect
11
+ class SeleniumConnect
12
+ # encapsulates the creation of a driver and a run
13
+ class Job
14
+
15
+ def initialize(config, report_factory)
16
+ @config = config
17
+ @report_factory = report_factory
18
+ end
19
+
20
+ # Creates and returns the driver, using options passed in
21
+ def start(opts = {})
22
+
23
+ # TODO this could be refactored out into an options parser of sorts
24
+ @config.description = opts[:name] if opts.has_key? :name
25
+
26
+ @driver = Runner.new(@config).driver
27
+ end
28
+
29
+ # Finishes the driver run, taking any data to help, returning report
30
+ def finish(opts = {})
31
+
32
+ # extracted from the earlier main finish
33
+ begin
34
+ @driver.quit
35
+ job_id = @driver.session_id
36
+ if @config.host == 'saucelabs'
37
+ if opts.has_key?(:failed) && opts[:failed]
38
+ fail_job job_id
39
+ if opts.has_key?(:failshot) && opts[:failshot]
40
+ save_last_screenshot job_id
41
+ end
42
+ end
43
+ if opts.has_key?(:passed) && opts[:passed]
44
+ pass_job job_id
45
+ end
46
+ data = fetch_logs(job_id)
47
+ report_data = symbolize_keys sauce_data: data
48
+ end
49
+ # rubocop:disable HandleExceptions
50
+ rescue Selenium::WebDriver::Error::WebDriverError
51
+ # rubocop:enable HandleExceptions
52
+ end
53
+
54
+ @report_factory.build :job, report_data
55
+ end
56
+
57
+ private
58
+
59
+ # TODO all this sauce stuff needs to be pulled out of the job class
60
+ # TODO need to put error handling around the sauce api requests
61
+ def save_last_screenshot(job_id)
62
+ begin
63
+ # Seemingly need to wait slightly for the images to be processed
64
+ sleep(2)
65
+ image = SauceWhisk::Jobs.fetch_asset job_id, 'final_screenshot.png'
66
+ image_file = File.join(Dir.getwd, @config.log, "failed_#{job_id}.png") if @config.log
67
+ File.open(image_file, 'w') { |f| f.write image }
68
+ rescue RestClient::ResourceNotFound
69
+ puts 'Unable to download image!'
70
+ end
71
+ end
72
+
73
+ def fail_job(job_id)
74
+ SauceWhisk::Jobs.fail_job job_id
75
+ end
76
+
77
+ def pass_job(job_id)
78
+ SauceWhisk::Jobs.pass_job job_id
79
+ end
80
+
81
+ def fetch_logs(job_id)
82
+ sauce_job = Sauce::Job.find(job_id)
83
+ # Seemingly need to wait slightly for the images to be processed
84
+ sleep(2)
85
+ server_log = SauceWhisk::Jobs.fetch_asset job_id, 'selenium-server.log'
86
+ log_file = File.join(Dir.getwd, @config.log, "sauce_job_#{job_id}.log") if @config.log
87
+ File.open(log_file, 'w') { |f| f.write server_log }
88
+ JSON.parse(sauce_job.to_json)
89
+ end
90
+
91
+ # TODO this should be pulled out into a generic report... or something
92
+ def symbolize_keys(hash)
93
+ hash.reduce({}) do |result, (key, value)|
94
+ new_key = key.class == String ? key.to_sym : key
95
+ new_value = value.class == Hash ? symbolize_keys(value) : value
96
+ result[new_key] = new_value
97
+ result
98
+ end
99
+ end
100
+ end
101
+ end
102
+
@@ -0,0 +1,17 @@
1
+ # Encoding: utf-8
2
+
3
+ # selenium connect
4
+ class SeleniumConnect
5
+ module Report
6
+ # report for a specific job
7
+ class JobReport
8
+
9
+ attr_reader :data
10
+
11
+ def initialize(data)
12
+ @data = data
13
+ end
14
+
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ # Encoding: utf-8
2
+
3
+ # selenium connect
4
+ class SeleniumConnect
5
+ module Report
6
+ # report for a connection
7
+ class MainReport
8
+
9
+ attr_reader :data
10
+
11
+ def initialize(data)
12
+ @data = data
13
+ end
14
+
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,25 @@
1
+ # Encoding: utf-8
2
+
3
+ require 'selenium_connect/report/job_report'
4
+ require 'selenium_connect/report/main_report'
5
+
6
+ # selenium connect
7
+ class SeleniumConnect
8
+ module Report
9
+ # creates report objects
10
+ class ReportFactory
11
+
12
+ def build(type, data)
13
+ # resource locator for report
14
+ case type
15
+ when :main
16
+ SeleniumConnect::Report::MainReport.new data
17
+ when :job
18
+ SeleniumConnect::Report::JobReport.new data
19
+ else
20
+ raise ArgumentError, "Report type \"#{type.to_s}\" unknown!"
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -1,13 +1,14 @@
1
1
  # Encoding: utf-8
2
2
 
3
- require 'selenium-connect/runners/firefox'
4
- require 'selenium-connect/runners/ie'
5
- require 'selenium-connect/runners/chrome'
6
- require 'selenium-connect/runners/phantomjs'
7
- require 'selenium-connect/runners/no_browser'
8
- require 'selenium-connect/runners/saucelabs'
9
-
10
- module SeleniumConnect
3
+ require 'selenium_connect/runners/firefox'
4
+ require 'selenium_connect/runners/ie'
5
+ require 'selenium_connect/runners/chrome'
6
+ require 'selenium_connect/runners/phantomjs'
7
+ require 'selenium_connect/runners/no_browser'
8
+ require 'selenium_connect/runners/saucelabs'
9
+
10
+ # selenium connect
11
+ class SeleniumConnect
11
12
  # Initializes the driver
12
13
  class Runner
13
14
  attr_reader :driver, :config
@@ -1,6 +1,6 @@
1
1
  # Encoding: utf-8
2
2
 
3
- module SeleniumConnect
3
+ class SeleniumConnect
4
4
  # Runner
5
5
  class Runner
6
6
  # Chrome browser runner
@@ -1,6 +1,6 @@
1
1
  # Encoding: utf-8
2
2
 
3
- module SeleniumConnect
3
+ class SeleniumConnect
4
4
  # Runner
5
5
  class Runner
6
6
  # Firefox browser runner
@@ -1,6 +1,6 @@
1
1
  # Encoding: utf-8
2
2
 
3
- module SeleniumConnect
3
+ class SeleniumConnect
4
4
  # Runner
5
5
  class Runner
6
6
  # IE Browser Runner
@@ -1,6 +1,6 @@
1
1
  # Encoding: utf-8
2
2
 
3
- module SeleniumConnect
3
+ class SeleniumConnect
4
4
  # Runner
5
5
  class Runner
6
6
  # No Browser Runner
@@ -1,6 +1,6 @@
1
1
  # Encoding: utf-8
2
2
 
3
- module SeleniumConnect
3
+ class SeleniumConnect
4
4
  # Runner
5
5
  class Runner
6
6
  # PhantomJS browser runner
@@ -2,7 +2,8 @@
2
2
 
3
3
  require 'sauce'
4
4
 
5
- module SeleniumConnect
5
+ # selenium connect
6
+ class SeleniumConnect
6
7
  # Runner
7
8
  class Runner
8
9
  # Sauce runner
@@ -1,6 +1,7 @@
1
1
  # Encoding: utf-8
2
2
 
3
- module SeleniumConnect
3
+ # selenium connect
4
+ class SeleniumConnect
4
5
  # Creates a server connection
5
6
  class Server
6
7
  attr_reader :configuration, :current_dir_path
@@ -1,12 +1,12 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'selenium-connect'
3
- s.version = '2.3.0'
3
+ s.version = '3.0.0'
4
4
  s.platform = Gem::Platform::RUBY
5
5
  s.authors = ['Dave Haeffner', 'Jason Fox']
6
6
  s.email = ['dave@arrgyle.com', 'jason@arrgyle.com']
7
7
  s.homepage = 'https://github.com/arrgyle/selenium-connect'
8
8
  s.summary = 'A stupid simple way to run your Selenium tests on localhost, against a Selenium Grid, or in the cloud (e.g. SauceLabs).'
9
- s.description = 'Added return data to a finish call to pass back relevent job details'
9
+ s.description = 'Major refactoring of the public api which now includes correct updating of sauce lab job status and fetching screenshots on failure'
10
10
  s.license = 'MIT'
11
11
 
12
12
  s.files = `git ls-files`.split($/)
@@ -17,8 +17,13 @@ Gem::Specification.new do |s|
17
17
  s.add_dependency 'selenium-webdriver'
18
18
  s.add_dependency 'rake'
19
19
  s.add_dependency 'sauce', '~> 2.4.4'
20
+ s.add_dependency 'sauce_whisk', '~> 0.0.8'
21
+ s.add_dependency 'curb', '~> 0.8.4'
20
22
 
21
- s.add_development_dependency 'rspec'
22
- s.add_development_dependency "rubocop", "~> 0.9.0"
23
+ s.add_development_dependency 'rspec', '~> 2.14.1'
24
+ s.add_development_dependency 'mocha', '~> 0.14.0'
25
+ s.add_development_dependency 'rubocop', '~> 0.9.0'
26
+ s.add_development_dependency 'guard-rspec', '~> 3.0.2'
27
+ s.add_development_dependency 'coveralls', '~> 0.6.7'
23
28
 
24
29
  end
@@ -0,0 +1,19 @@
1
+ # Encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+ require 'selenium_connect'
5
+
6
+ describe 'Chrome', selenium: true do
7
+
8
+ it 'localhost' do
9
+ config = SeleniumConnect::Configuration.new browser: 'chrome'
10
+ sc = SeleniumConnect.start config
11
+ job = sc.create_job
12
+ driver = job.start
13
+
14
+ execute_simple_test driver
15
+
16
+ job.finish
17
+ sc.finish
18
+ end
19
+ end
@@ -0,0 +1,55 @@
1
+ # Encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+ require 'selenium_connect'
5
+
6
+ describe 'Firefox', selenium: true do
7
+
8
+ it 'blank config' do
9
+ @config = SeleniumConnect::Configuration.new
10
+ end
11
+
12
+ it 'localhost' do
13
+ @config = SeleniumConnect::Configuration.new host: 'localhost'
14
+ end
15
+
16
+ it 'local jar file specified' do
17
+ opts = {
18
+ host: 'localhost',
19
+ jar: "#{Dir.pwd}/bin/selenium-server-standalone-2.33.0.jar"
20
+ }
21
+ @config = SeleniumConnect::Configuration.new opts
22
+ end
23
+
24
+ it 'profile name' do
25
+ pending 'requires machine setup to run, and need a public example'
26
+ @config = SeleniumConnect::Configuration.new profile_name: 'YourProfileNameGoesHere'
27
+ end
28
+
29
+ it 'profile path' do
30
+ pending 'need to add a profile to the repo'
31
+ @config = SeleniumConnect::Configuration.new profile_path: "#{Dir.pwd}/path/to/profile"
32
+ end
33
+
34
+ it 'browser path' do
35
+ # example only works on Mac
36
+ opts = {
37
+ browser: 'firefox',
38
+ browser_path: '/Applications/Firefox.app/Contents/MacOS/firefox'
39
+ }
40
+ @config = SeleniumConnect::Configuration.new opts
41
+ end
42
+
43
+ after(:each) do
44
+ # execute a simple test with the configuration
45
+ unless @config.nil?
46
+ sc = SeleniumConnect.start @config
47
+ job = sc.create_job
48
+ driver = job.start
49
+ execute_simple_test driver
50
+ job.finish
51
+ sc.finish
52
+ end
53
+ end
54
+
55
+ end
@@ -0,0 +1,33 @@
1
+ # Encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+ require 'selenium_connect'
5
+
6
+ describe 'Headless', selenium: true do
7
+
8
+ let(:google) { Google.new(SeleniumConnect.start) }
9
+ let(:quit) { SeleniumConnect.finish }
10
+
11
+ before(:each) do
12
+ config = SeleniumConnect::Configuration.new browser: 'phantomjs'
13
+ @sc = SeleniumConnect.start config
14
+ @job = @sc.create_job
15
+ @driver = @job.start
16
+ end
17
+
18
+ it 'should run a basic test with phantom js' do
19
+ execute_simple_test @driver
20
+ end
21
+
22
+ it 'should not find something on a page' do
23
+ google = ExamplePageObject.new @driver
24
+ google.visit
25
+ google.page_title.should_not include('Poogle')
26
+ end
27
+
28
+ after(:each) do
29
+ @job.finish
30
+ @sc.finish
31
+ end
32
+
33
+ end
@@ -0,0 +1,24 @@
1
+ # Encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+ require 'selenium_connect'
5
+
6
+ describe 'IE', selenium: true do
7
+
8
+ it 'with Selenium Grid' do
9
+ pending 'not yet implemented'
10
+ opts = {
11
+ host: '192.168.1.139',
12
+ browser: 'ie'
13
+ }
14
+ config = SeleniumConnect::Configuration.new opts
15
+ sc = SeleniumConnect.start config
16
+ job = sc.create_job
17
+ driver = job.start
18
+ execute_simple_test driver
19
+ job.finish
20
+ sc.finish
21
+ end
22
+
23
+ end
24
+