shoot 2.0.2 → 2.1.0

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
  SHA1:
3
- metadata.gz: 7e10dbd0bfc3ff30229957a90d50477a671c0aab
4
- data.tar.gz: e619ce09449a34dbceffa72e9fc41ce013897bae
3
+ metadata.gz: 152d35943f02692f5c763b5928e6dcfcf0c51e29
4
+ data.tar.gz: 51152e373355366c011881fbb8b6aecca33444a8
5
5
  SHA512:
6
- metadata.gz: a4f0d7327b131b72f4d7322cc8adeb8aa3836c152cdce5137aa08bfafdeca6b66532b5769629ff930a2e20b0c6df6729c464a156e5e5be7ad76481f29274b99c
7
- data.tar.gz: 0feca96a4fa38dbb160d0717cc7ae4ad2bd717faefa8a511aa6d998058cda866540ec27c7264f53d5461c0f785fc4b94fea98fcb7a9c450fb94436c0921bac53
6
+ metadata.gz: 8ae30e0c7ba313cab8298b866d9ffa0750c0e16a26242d8eebb5bf77efff96db56b27ab5c1c9d81d110f1ea92c8de0ca9df132a0221573c5c3c50106273e1a7d
7
+ data.tar.gz: 9edf0ae57d9cea0a13df09202a63f6fe9c4e08aa4b0e5ebbe079d143a2578a2115834b0259d4e69c4ed9d1d93fdbb7761c3f95eb6df14f09cfa103baa235f54b
data/Changelog.md CHANGED
@@ -1,3 +1,11 @@
1
+ # 2.1.0
2
+
3
+ - Adds Ngrok and NgrokPow class to make forwarding much easier;
4
+ - Adds a list of _ad hoc_ emulators BrowserStack provides for iPhones/iPads that is not on the API; 😢
5
+ - Writes a backtrace files in the appropriate folder if the thing explodes (both external and internal issues);
6
+ - Updates the Changelog to contain this.
7
+
8
+
1
9
  # 2.0.0
2
10
 
3
11
  - Adds interactive mode (`shoot -i`);
data/README.md CHANGED
@@ -145,6 +145,38 @@ You got the idea.
145
145
  shoot update # Update browser list (WARNING: will override active browsers)
146
146
  shoot version, --version, -v # Shoot version
147
147
 
148
+ ### Using ngrok
149
+
150
+ In order to access your local development environment on BrowserStack you need to forward it somehow to the external work (a.k.a. the internet). BrowserStack has it's own forwarded, but ngrok is better. If you wanna use it:
151
+
152
+ 1. Install it from [https://ngrok.com/download](https://ngrok.com/download)
153
+
154
+ 2. Enable subdomains by registering.
155
+
156
+ 3. Use the `Shoot::Ngrok` class in your test, like this:
157
+
158
+ ``` ruby
159
+ def my_test
160
+ my_server = Shoot::Ngrok(12345)
161
+ visit my_server.url
162
+ end
163
+ ```
164
+
165
+ Where `12345` is the port of your local server. The default is `3000`, since I believe you're probably using Rails.
166
+
167
+ #### What if I'm using pow?
168
+
169
+ If you're using pow, skip step 3 above and do it like this instead:
170
+
171
+ ``` ruby
172
+ def my_test
173
+ my_server = Shoot::NgrokPow(:my_server_folder)
174
+ visit my_server.url
175
+ end
176
+ ```
177
+
178
+ NgrokPow will create another symlink of your server folder with a unique name and forward it correctly to ngrok. This symlink will be properly removed at the end of the execution of shoot.
179
+
148
180
  ## Contributing
149
181
 
150
182
  1. Fork it ( https://github.com/joaomilho/shoot/fork )
@@ -0,0 +1,119 @@
1
+ require 'json'
2
+
3
+ class Hash
4
+ def symbolize_keys
5
+ self.keys.each do |key|
6
+ self[key.to_sym] = self.delete(key)
7
+ end
8
+ self
9
+ end
10
+ end
11
+
12
+
13
+ module Shoot
14
+ class Browser
15
+ BROWSERS_PATH = '.screenshots/.browsers.json'
16
+ EMULATORS_UNAVAILABLE_ON_THE_API = ["iPad 3rd", "iPad 3rd (6.0)", "iPad Mini", "iPad 4th", "iPhone 4S", "iPhone 4S (6.0)", "iPhone 5", "iPhone 5S"].map do |device|
17
+ {
18
+ browser: "iPhone",
19
+ os: "MAC",
20
+ device: device,
21
+ emulator: true
22
+ }
23
+ end
24
+
25
+ def self.all
26
+ @@all ||= fetch_json.map { |browser| Browser.new(browser.symbolize_keys) }
27
+ end
28
+
29
+ def self.activate(ids)
30
+ update(select_by_ids(ids), :activate)
31
+ end
32
+
33
+ def self.deactivate(ids)
34
+ update(select_by_ids(ids), :deactivate)
35
+ end
36
+
37
+ def self.deactivate_all
38
+ update(active, :deactivate)
39
+ end
40
+
41
+ def self.active
42
+ all.select(&:active)
43
+ end
44
+
45
+ def self.update_json
46
+ File.write(BROWSERS_PATH, JSON.dump(fetch_and_prepare))
47
+ end
48
+
49
+ def self.filter(filter)
50
+ all.select { |browser| browser.inspect =~ /#{filter}/i }
51
+ end
52
+
53
+ def self.select_by_ids(ids)
54
+ ids = ids.map(&:to_i)
55
+ all.select { |browser| ids.include?(browser.id) }
56
+ end
57
+
58
+ def self.save
59
+ File.write(BROWSERS_PATH, JSON.pretty_generate(all.map(&:to_h)))
60
+ end
61
+
62
+ attr_reader :id, :os, :os_version, :browser, :device, :browser_version, :active, :emulator
63
+ def initialize(id:, os:, browser:, device:, os_version: nil, browser_version: nil, active: false, emulator: false)
64
+ @id = id
65
+ @os = os
66
+ @os_version = os_version
67
+ @browser = browser
68
+ @device = device
69
+ @browser_version = browser_version
70
+ @active = active
71
+ @emulator = emulator
72
+ end
73
+
74
+ def activate
75
+ @active = true
76
+ end
77
+
78
+ def deactivate
79
+ @active = false
80
+ end
81
+
82
+ def to_h
83
+ {
84
+ id: id,
85
+ os: os,
86
+ os_version: os_version,
87
+ browser: browser,
88
+ device: device,
89
+ browser_version: browser_version,
90
+ active: active,
91
+ emulator: emulator
92
+ }
93
+ end
94
+
95
+ private
96
+
97
+ def self.update(browsers, action)
98
+ browsers.map(&action)
99
+ save
100
+ browsers
101
+ end
102
+
103
+ def self.fetch_json
104
+ update_json unless File.exist?(BROWSERS_PATH)
105
+ JSON.parse(File.read(BROWSERS_PATH))
106
+ end
107
+
108
+ def self.fetch_and_prepare
109
+ require 'rest_client'
110
+ json = JSON.parse(RestClient.get("https://#{ENV['BROWSERSTACK_USER']}:#{ENV['BROWSERSTACK_KEY']}@www.browserstack.com/automate/browsers.json"))
111
+ json += EMULATORS_UNAVAILABLE_ON_THE_API
112
+ json.each_with_index do |browser, index|
113
+ browser['id'] = index
114
+ end
115
+ json
116
+ end
117
+
118
+ end
119
+ end
data/lib/shoot/cli.rb CHANGED
@@ -1,12 +1,13 @@
1
1
  require 'thor'
2
- require 'json'
2
+ require 'benchmark'
3
3
  require 'highline/import'
4
4
 
5
5
  module Shoot
6
6
  class CLI < Thor
7
+ include UI
8
+
7
9
  require 'fileutils'
8
10
  FileUtils::mkdir_p '.screenshots'
9
- BROWSERS_PATH = '.screenshots/.browsers.json'
10
11
  map %w[--version -v] => :version
11
12
  map %w[--interactive -i] => :interactive
12
13
 
@@ -15,29 +16,28 @@ module Shoot
15
16
  puts Shoot::VERSION
16
17
  end
17
18
 
19
+ INTERACTIVE_COMMANDS = {
20
+ active: ->(_) { active },
21
+ activate: ->(params){ activate(*params.split(" ")) },
22
+ deactivate: ->(params){ deactivate(*params.split(" ")) },
23
+ deactivate_all: ->(_) { deactivate_all },
24
+ list: ->(params){ list(params) },
25
+ open: ->(_) { open },
26
+ test: ->(params){ test(params) },
27
+ scenario: ->(params){ scenario(params) },
28
+ update: ->(_) { update },
29
+ exit: ->(_) { @exit = true }
30
+ }
31
+
18
32
  desc 'interactive, --interactive, -i', 'Interactive mode'
19
33
  def interactive
20
34
  @exit = false
21
-
22
- available_commands = {
23
- active: ->(_) { active },
24
- activate: ->(params){ activate(*params.split(" ")) },
25
- deactivate: ->(params){ deactivate(*params.split(" ")) },
26
- deactivate_all: ->(_) { deactivate_all },
27
- list: ->(params){ list(params) },
28
- open: ->(_) { open },
29
- test: ->(params){ test(params) },
30
- scenario: ->(params){ scenario(params) },
31
- update: ->(_) { update },
32
- exit: ->(_) { @exit = true }
33
- }
34
-
35
35
  while ! @exit
36
36
  choose do |menu|
37
37
  menu.layout = :menu_only
38
38
  menu.shell = true
39
39
 
40
- available_commands.each do |command_name, command_action|
40
+ INTERACTIVE_COMMANDS.each do |command_name, command_action|
41
41
  menu.choice(command_name, desc(command_name)){|_, details| command_action.call(details) }
42
42
  end
43
43
  end
@@ -46,27 +46,27 @@ module Shoot
46
46
 
47
47
  desc 'open', 'Opens all screenshots taken'
48
48
  def open
49
- open_all_screenshots
49
+ `open #{Dir.glob(".screenshots/**/*.png").join(" ")}`
50
50
  end
51
51
 
52
52
  desc 'list [FILTER]', 'List all platforms. Optionally passing a filter'
53
53
  def list(filter = nil)
54
- table json.select { |p| p.inspect =~ /#{filter}/i }
54
+ table filter ? Browser.filter(filter) : Browser.all
55
55
  end
56
56
 
57
57
  desc 'active', 'List active platforms.'
58
58
  def active
59
- table _active
59
+ table Browser.active
60
60
  end
61
61
 
62
62
  desc 'scenario PATH', 'Runs the given scenario or all files in a directory on all active platforms'
63
63
  def scenario(path)
64
- files = File.directory?(path) ? Dir.glob("#{path}/*.rb") : [path]
64
+ scenarios = File.directory?(path) ? Dir.glob("#{path}/*.rb") : [path]
65
65
 
66
66
  elapsed_time do
67
- _active.each do |config|
68
- files.each do |file|
69
- run file, config
67
+ Browser.active.each do |browser|
68
+ scenarios.each do |scenario|
69
+ run scenario, browser
70
70
  end
71
71
  end
72
72
  print set_color("\nAll tests finished", :blue)
@@ -75,44 +75,40 @@ module Shoot
75
75
 
76
76
  desc 'test PATH', 'Runs the given scenario or all files in a directory on a local phantomjs'
77
77
  def test(path)
78
- files = File.directory?(path) ? Dir.glob("#{path}/*.rb") : [path]
78
+ scenarios = File.directory?(path) ? Dir.glob("#{path}/*.rb") : [path]
79
79
  elapsed_time do
80
- files.each{|file| run file, nil }
80
+ scenarios.each{|scenario| run scenario }
81
81
  print set_color("\nAll tests finished", :blue)
82
82
  end
83
83
  end
84
84
 
85
85
  desc 'activate IDs', 'Activate platforms, based on IDs'
86
86
  def activate(*ids)
87
- _activate(ids)
87
+ return puts "No ids provided, e.g. 'activate 123'" if ids.empty?
88
+ table Browser.activate(ids)
88
89
  end
89
90
 
90
91
  desc 'deactivate IDs', 'Deactivate platforms, based on IDs'
91
92
  def deactivate(*ids)
92
- _deactivate(ids)
93
+ return puts "No ids provided, e.g. 'deactivate 123'" if ids.empty?
94
+ table Browser.deactivate(ids)
93
95
  end
94
96
 
95
97
  desc 'deactivate_all', 'Deactivate all the platforms'
96
98
  def deactivate_all
97
- _active.each do |child|
98
- child['active'] = false
99
- end
100
- save_json
99
+ Browser.deactivate_all
101
100
  end
102
101
 
103
102
  desc 'update', 'Update browser list (WARNING: will override active browsers)'
104
103
  def update
105
- update_json
104
+ Browser.update_json
106
105
  list
107
106
  end
108
107
 
109
108
  no_commands do
110
- def elapsed_time
111
- require 'benchmark'
112
109
 
113
- elapsed_time = Benchmark.measure do
114
- yield
115
- end
110
+ def elapsed_time
111
+ elapsed_time = Benchmark.measure { yield }
116
112
  print set_color " (#{elapsed_time.real.to_i}s)\n", :blue
117
113
  end
118
114
 
@@ -120,99 +116,23 @@ module Shoot
120
116
  CLI.commands[command.to_s].description rescue nil
121
117
  end
122
118
 
123
- def _activate(ids)
124
- return puts "No ids provided, e.g. 'activate 123'" if ids.empty?
125
- ids.map!(&:to_i)
126
- ids.each { |id| json[id]['active'] = true }
127
- save_json
128
- table json.select{|item| ids.include?(item['id']) }
129
- end
130
-
131
- def _deactivate(ids)
132
- return puts "No ids provided, e.g. 'deactivate 123'" if ids.empty?
133
- ids.map!(&:to_i)
134
- ids.each { |id| json[id]['active'] = false }
135
- save_json
136
- table json.select{|item| ids.include?(item['id']) }
137
- end
138
-
139
- def open_all_screenshots
140
- `open #{Dir.glob(".screenshots/**/*.png").join(" ")}`
141
- end
142
-
143
- def run(file, config = nil)
144
- klass = get_const_from_file(file)
145
- instance = klass.new(config)
146
- puts set_color instance.platform_name, :white, :bold
147
- klass.instance_methods(false).each do |method|
148
- print set_color " ➥ #{klass}##{method} ... ", :white, :bold
119
+ def run(scenario, browser = nil)
120
+ runner = ScenarioRunner.new(scenario, browser)
121
+ puts set_color runner.platform_name, :white, :bold
122
+ runner.each_method do |method|
123
+ print set_color " ➥ #{runner.klass}##{method} ... ", :white, :bold
149
124
  error = nil
150
125
 
151
126
  elapsed_time do
152
- ok, error = instance.run(method)
127
+ ok, error = runner.run(method)
153
128
 
154
129
  print ok ? set_color("OK", :green) : set_color("FAILED", :red)
155
130
  end
156
131
  puts set_color " ⚠ #{error}", :red if error
157
132
  end
158
- instance.ok
159
- end
160
-
161
- def require_file(file)
162
- require Dir.pwd + '/' + file
163
- end
164
133
 
165
- def constantize_file_name(file)
166
- klass_name = File.basename(file, '.rb').split('_').map(&:capitalize).join
167
- Kernel.const_get(klass_name)
168
134
  end
169
135
 
170
- def get_const_from_file(file)
171
- require_file(file)
172
- constantize_file_name(file)
173
- end
174
-
175
- def table(browsers)
176
- table = browsers.map do |p|
177
- to_row(p)
178
- end.unshift(['ID', 'OS #', 'Browser #', 'Device'])
179
- print_table table, truncate: true
180
- end
181
-
182
- def to_row(p)
183
- [
184
- set_color(p['id'].to_s, p['active'] ? :green : :red),
185
- "#{p['os']} #{p['os_version']}",
186
- "#{p['browser']} #{p['browser_version']}",
187
- p['device']
188
- ]
189
- end
190
-
191
- def update_json
192
- File.write(BROWSERS_PATH, JSON.dump(fetch_json_and_prepare))
193
- end
194
-
195
- def json
196
- update_json unless File.exist?(BROWSERS_PATH)
197
- @json ||= JSON.parse(File.read(BROWSERS_PATH))
198
- end
199
-
200
- def _active
201
- @active ||= json.select { |p| p['active'] }
202
- end
203
-
204
- def save_json
205
- File.write(BROWSERS_PATH, JSON.pretty_generate(json))
206
- end
207
-
208
- def fetch_json_and_prepare
209
- require 'rest_client'
210
- JSON.parse(RestClient.get("https://#{ENV['BROWSERSTACK_USER']}:#{ENV['BROWSERSTACK_KEY']}@www.browserstack.com/automate/browsers.json")).tap do |json|
211
- json.each_with_index do |browser, index|
212
- browser['id'] = index
213
- end
214
- end
215
- end
216
136
  end
217
137
  end
218
138
  end
@@ -0,0 +1,23 @@
1
+ require 'childprocess'
2
+ require 'forwardable'
3
+ require 'securerandom'
4
+
5
+ module Shoot
6
+ class Ngrok
7
+ extend Forwardable
8
+ def_delegators :@process, :start, :stop, :exited?
9
+
10
+ def initialize(port = 3000)
11
+ @process = ChildProcess.build("ngrok", "-log=stdout", "-subdomain=#{subdomain}", port.to_s)
12
+ start
13
+ end
14
+
15
+ def subdomain
16
+ @subdomain ||= "shoot-#{Time.now.to_i}-#{SecureRandom.random_number(10**8)}"
17
+ end
18
+
19
+ def url
20
+ @url ||= "http://#{subdomain}.ngrok.com"
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,13 @@
1
+ module Shoot
2
+ class NgrokPow < Ngrok
3
+ def initialize(server)
4
+ `ln -s ~/.pow/#{server} ~/.pow/#{subdomain}`
5
+ @process = ChildProcess.build("ngrok", "-log=stdout", "-subdomain=#{subdomain}", "#{subdomain}.dev:80")
6
+ start
7
+
8
+ at_exit do
9
+ `rm ~/.pow/#{subdomain}`
10
+ end
11
+ end
12
+ end
13
+ end
@@ -43,51 +43,60 @@ class Shoot::Scenario
43
43
  def run(method)
44
44
  @current_method = method
45
45
  send(method)
46
- #Kernel.sleep(1) # Just in case
47
46
  shoot(:finish)
48
47
  [true, nil]
49
48
  rescue => e
50
- #puts "FAILED #{method}: #{e.inspect}"
49
+ File.write("#{directory}/backtrace.txt", e.backtrace.join("\n"))
51
50
  shoot(:failed)
52
51
  [false, e]
53
52
  end
54
53
 
55
- def ok
54
+ def quit
56
55
  page.driver.quit
57
56
  end
58
57
 
59
58
  def platform_name
60
- @platform_name ||= if @platform['device']
61
- @platform['device']
59
+ @platform_name ||= if @platform.device
60
+ @platform.device
62
61
  else
63
- name_items = %w(browser browser_version os os_version)
64
- @platform.values_at(*name_items).join(' ')
62
+ [
63
+ @platform.browser,
64
+ @platform.browser_version,
65
+ @platform.os,
66
+ @platform.os_version
67
+ ].join(' ')
65
68
  end
66
69
  end
67
70
 
68
71
  private
69
72
 
70
- def shoot(label)
71
- directory = ".screenshots/#{platform_name.to_s.gsub(" ", "_")}/#{self.class.name}/#{@current_method}"
72
- unless Dir.exist?(directory)
73
- require 'fileutils'
74
- FileUtils::mkdir_p directory
73
+ def directory
74
+ ".screenshots/#{platform_name.to_s.gsub(" ", "_")}/#{self.class.name}/#{@current_method}".tap do |dir|
75
+ unless Dir.exist?(dir)
76
+ require 'fileutils'
77
+ FileUtils::mkdir_p dir
78
+ end
75
79
  end
80
+ end
76
81
 
82
+ def shoot(label)
77
83
  save_screenshot("#{directory}/#{label}.png")
84
+ rescue => e
85
+ File.write("#{directory}/#{label}.error.txt", %(#{e.inspect}\n\n#{e.backtrace.join("\n")}))
78
86
  end
79
87
 
80
88
  def config_capabilities # rubocop:disable AbcSize
81
89
  @capabilities = Selenium::WebDriver::Remote::Capabilities.new
82
- @capabilities[:browser] = @platform['browser']
83
- @capabilities[:browser_version] = @platform['browser_version']
84
- @capabilities[:os] = @platform['os']
85
- @capabilities[:os_version] = @platform['os_version']
90
+ @capabilities[:browser] = @platform.browser
91
+ @capabilities[:browser_version] = @platform.browser_version
92
+ @capabilities[:os] = @platform.os
93
+ @capabilities[:os_version] = @platform.os_version
86
94
  @capabilities['browserstack.debug'] = 'true'
87
- @capabilities[:name] = "Digital Goods - #{@platform}"
88
- @capabilities[:browserName] = @platform['browser']
89
- @capabilities[:platform] = @platform['os']
90
- @capabilities[:device] = @platform['device'] if @platform['device']
95
+ @capabilities[:name] = "Digital Goods - #{@platform.to_h}"
96
+ @capabilities[:browserName] = @platform.browser
97
+ @capabilities[:platform] = @platform.os
98
+ @capabilities[:device] = @platform.device if @platform.device
99
+ @capabilities[:emulator] = @platform.emulator
91
100
  end
92
101
 
93
102
  end
@@ -0,0 +1,40 @@
1
+ module Shoot
2
+ class ScenarioRunner
3
+ attr_reader :klass
4
+ def initialize(scenario, browser = nil)
5
+ @klass = get_const_from_file(scenario)
6
+ @instance = @klass.new(browser)
7
+ end
8
+
9
+ def platform_name
10
+ @instance.platform_name
11
+ end
12
+
13
+ def each_method
14
+ @klass.instance_methods(false).each do |method|
15
+ yield(method)
16
+ end
17
+ @instance.quit
18
+ end
19
+
20
+ def run(method)
21
+ @instance.run(method)
22
+ end
23
+
24
+ private
25
+
26
+ def require_file(file)
27
+ require Dir.pwd + '/' + file
28
+ end
29
+
30
+ def constantize_file_name(file)
31
+ klass_name = File.basename(file, '.rb').split('_').map(&:capitalize).join
32
+ Kernel.const_get(klass_name)
33
+ end
34
+
35
+ def get_const_from_file(file)
36
+ require_file(file)
37
+ constantize_file_name(file)
38
+ end
39
+ end
40
+ end
data/lib/shoot/ui.rb ADDED
@@ -0,0 +1,24 @@
1
+ module Shoot
2
+ module UI
3
+ TABLE_HEADER = ['ID', 'OS #', 'Browser #', 'Device', 'Emulator']
4
+
5
+ def table(browsers)
6
+ table = browsers.map do |browser|
7
+ to_row(browser)
8
+ end.unshift(TABLE_HEADER)
9
+ print_table table, truncate: true
10
+ end
11
+
12
+ private
13
+
14
+ def to_row(browser)
15
+ [
16
+ set_color(browser.id.to_s, browser.active ? :green : :red),
17
+ "#{browser.os} #{browser.os_version}",
18
+ "#{browser.browser} #{browser.browser_version}",
19
+ browser.device,
20
+ browser.emulator ? 'Yes' : set_color('No', :black)
21
+ ]
22
+ end
23
+ end
24
+ end
data/lib/shoot/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Shoot
2
- VERSION = "2.0.2"
2
+ VERSION = "2.1.0"
3
3
  end
data/lib/shoot.rb CHANGED
@@ -1,5 +1,10 @@
1
1
  module Shoot
2
- autoload :CLI, "shoot/cli"
3
- autoload :Scenario, "shoot/scenario"
4
- autoload :VERSION, "shoot/version"
2
+ autoload :Browser, "shoot/browser"
3
+ autoload :CLI, "shoot/cli"
4
+ autoload :Ngrok, "shoot/ngrok"
5
+ autoload :NgrokPow, "shoot/ngrok_pow"
6
+ autoload :Scenario, "shoot/scenario"
7
+ autoload :ScenarioRunner, "shoot/scenario_runner"
8
+ autoload :UI, "shoot/ui"
9
+ autoload :VERSION, "shoot/version"
5
10
  end
data/shoot.gemspec CHANGED
@@ -28,4 +28,5 @@ Gem::Specification.new do |spec|
28
28
  spec.add_dependency "rest-client", "~> 1.7"
29
29
  spec.add_dependency "poltergeist", "~> 1.6"
30
30
  spec.add_dependency "highline", "~> 1.7"
31
+ spec.add_dependency "childprocess", "~> 0.5"
31
32
  end
data/spec/cli_spec.rb CHANGED
@@ -1,4 +1,4 @@
1
- require_relative '../lib/shoot/cli'
1
+ require_relative '../lib/shoot'
2
2
 
3
3
  describe 'Shoot::CLI' do
4
4
  subject(:cli) do
@@ -7,18 +7,18 @@ describe 'Shoot::CLI' do
7
7
 
8
8
  let(:mock_json) do
9
9
  [
10
- {os: "Foo", os_version: "Foo 1", browser: "Foo browser", device: nil, browser_version: "6.0", id: 0, 'active' => false},
11
- {os: "Bar", os_version: "Bar 2", browser: "Bar browser", device: nil, browser_version: "7.0", id: 1, 'active' => true}
10
+ {id: 0, os: "Foo", os_version: "Foo 1", browser: "Foo browser", device: nil, browser_version: "6.0", active: false, emulator: false},
11
+ {id: 1, os: "Bar", os_version: "Bar 2", browser: "Bar browser", device: nil, browser_version: "7.0", active: true, emulator: false}
12
12
  ]
13
13
  end
14
14
 
15
15
  before do
16
- allow(cli).to receive(:json).and_return(mock_json)
16
+ allow(Shoot::Browser).to receive(:fetch_json).and_return(mock_json)
17
+ allow(cli).to receive(:table) {|arg| arg.map(&:to_h) }
17
18
  end
18
19
 
19
20
  describe 'list' do
20
21
  before do
21
- allow(cli).to receive(:table) {|arg| arg }
22
22
  end
23
23
 
24
24
  context 'list all' do
@@ -36,10 +36,6 @@ describe 'Shoot::CLI' do
36
36
  end
37
37
 
38
38
  describe 'active' do
39
- before do
40
- allow(cli).to receive(:table) {|arg| arg }
41
- end
42
-
43
39
  it 'displays the active browsers' do
44
40
  expect(cli.active).to eq([mock_json[1]])
45
41
  end
@@ -48,42 +44,44 @@ describe 'Shoot::CLI' do
48
44
  describe 'activate' do
49
45
  before do
50
46
  allow(cli).to receive(:table) {|arg| arg }
51
- allow(cli).to receive(:save_json)
47
+ allow(Shoot::Browser).to receive(:save)
52
48
  end
53
49
 
54
50
  it 'activates the browser' do
55
- expect{ cli.activate(0) }.to change{ mock_json[0]['active'] }.from(false).to(true)
56
- expect(cli).to have_received(:save_json)
51
+ expect{ cli.activate(0) }.to change{ Shoot::Browser.all[0].active }.from(false).to(true)
52
+ expect(Shoot::Browser).to have_received(:save)
57
53
  end
58
54
  end
59
55
 
60
56
  describe 'deactivate' do
61
57
  before do
62
58
  allow(cli).to receive(:table) {|arg| arg }
63
- allow(cli).to receive(:save_json)
59
+ allow(Shoot::Browser).to receive(:save)
64
60
  end
65
61
 
66
62
  it 'deactivates the browser' do
67
- expect{ cli.deactivate(1) }.to change{ mock_json[1]['active'] }.from(true).to(false)
68
- expect(cli).to have_received(:save_json)
63
+ Shoot::Browser.all[1].activate
64
+ expect{ cli.deactivate(1) }.to change{ Shoot::Browser.all[1].active }.from(true).to(false)
65
+ expect(Shoot::Browser).to have_received(:save)
69
66
  end
70
67
  end
71
68
 
72
69
  describe 'deactivate_all' do
73
70
  before do
74
71
  allow(cli).to receive(:table) {|arg| arg }
75
- allow(cli).to receive(:save_json)
72
+ allow(Shoot::Browser).to receive(:save)
76
73
  end
77
74
 
78
75
  it 'deactivates the browser' do
79
- expect{ cli.deactivate_all }.to change{ mock_json[1]['active'] }.from(true).to(false)
80
- expect(cli).to have_received(:save_json)
76
+ Shoot::Browser.all[1].activate
77
+ expect{ cli.deactivate_all }.to change{ Shoot::Browser.all[1].active }.from(true).to(false)
78
+ expect(Shoot::Browser).to have_received(:save)
81
79
  end
82
80
  end
83
81
 
84
82
  describe 'scenario' do
85
83
  before do
86
- allow(cli).to receive(:_active).and_return(["foo"])
84
+ allow(Shoot::Browser).to receive(:active).and_return(["foo"])
87
85
  allow(cli).to receive(:run)
88
86
  end
89
87
 
@@ -102,7 +100,7 @@ describe 'Shoot::CLI' do
102
100
 
103
101
  it 'runs scenario' do
104
102
  cli.test('foo.rb')
105
- expect(cli).to have_received(:run).with("foo.rb", nil)
103
+ expect(cli).to have_received(:run).with("foo.rb")
106
104
  end
107
105
  end
108
106
 
@@ -115,8 +113,8 @@ describe 'Shoot::CLI' do
115
113
 
116
114
  it 'runs scenario' do
117
115
  cli.test('foo')
118
- expect(cli).to have_received(:run).with("foo/bar.rb", nil)
119
- expect(cli).to have_received(:run).with("foo/baz.rb", nil)
116
+ expect(cli).to have_received(:run).with("foo/bar.rb")
117
+ expect(cli).to have_received(:run).with("foo/baz.rb")
120
118
  end
121
119
  end
122
120
  end
@@ -129,9 +127,9 @@ describe 'Shoot::CLI' do
129
127
  end
130
128
  allow_any_instance_of(Foo).to receive(:run).and_return([true, ""])
131
129
  allow_any_instance_of(Foo).to receive(:platform_name)
132
- expect_any_instance_of(Foo).to receive(:ok)
130
+ expect_any_instance_of(Foo).to receive(:quit)
133
131
 
134
- allow(cli).to receive(:get_const_from_file).with("foo.rb").and_return(Foo)
132
+ allow_any_instance_of(Shoot::ScenarioRunner).to receive(:get_const_from_file).with("foo.rb").and_return(Foo)
135
133
  end
136
134
 
137
135
  it 'runs scenario' do
@@ -8,14 +8,13 @@ describe 'Shoot::Scenario' do
8
8
  allow(Capybara).to receive(:register_driver).with("browser 5.0 os 22.0")
9
9
  allow(Capybara).to receive(:current_driver=).with("browser 5.0 os 22.0")
10
10
  allow(FileUtils).to receive(:mkdir_p)
11
- allow(Kernel).to receive(:sleep)
12
11
 
13
- @scenario = Shoot::Scenario.new({
12
+ @scenario = Shoot::Scenario.new(OpenStruct.new({
14
13
  'browser' => 'browser',
15
14
  'browser_version' => '5.0',
16
15
  'os' => 'os',
17
16
  'os_version' => '22.0'
18
- })
17
+ }))
19
18
 
20
19
  allow(@scenario).to receive(:foo)
21
20
  allow(@scenario).to receive(:save_screenshot)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shoot
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.2
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Juan Lulkin
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-05-25 00:00:00.000000000 Z
11
+ date: 2015-06-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -136,6 +136,20 @@ dependencies:
136
136
  - - "~>"
137
137
  - !ruby/object:Gem::Version
138
138
  version: '1.7'
139
+ - !ruby/object:Gem::Dependency
140
+ name: childprocess
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: '0.5'
146
+ type: :runtime
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: '0.5'
139
153
  description: A helper to take shots on BrowserStack. Run the shoot binary for more
140
154
  info.
141
155
  email:
@@ -154,8 +168,13 @@ files:
154
168
  - Rakefile
155
169
  - bin/shoot
156
170
  - lib/shoot.rb
171
+ - lib/shoot/browser.rb
157
172
  - lib/shoot/cli.rb
173
+ - lib/shoot/ngrok.rb
174
+ - lib/shoot/ngrok_pow.rb
158
175
  - lib/shoot/scenario.rb
176
+ - lib/shoot/scenario_runner.rb
177
+ - lib/shoot/ui.rb
159
178
  - lib/shoot/version.rb
160
179
  - shoot.gemspec
161
180
  - spec/cli_spec.rb