shoot 1.1.0 → 2.0.0
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/Changelog.md +21 -0
- data/lib/shoot/cli.rb +101 -26
- data/lib/shoot/scenario.rb +19 -0
- data/lib/shoot/version.rb +1 -1
- data/shoot.gemspec +2 -1
- data/spec/cli_spec.rb +8 -7
- metadata +24 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 675f708a7fe175d332fea879546b0b1f3da65b01
|
4
|
+
data.tar.gz: 6503def1d598f295ed6cd8c32c36cfb14bb5b786
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 50f3f4c3492cba7e62ed7cdd839bf126b3b2b05e5e1f8770e3e8af28380797ec4f9b67bbc65c5b363d863efd704b8f2bfd2502090e988226feccc8af3562ab66
|
7
|
+
data.tar.gz: a0ae49e4ce89ea9ccfc782e84a1974d30bd21b4bc8a2fa7ce21a33999b277fdaa37c4b18e32a8a8e2ad742f1a55698bc31eb8df55a1fdc337e51d55a8dfc4a13
|
data/Changelog.md
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# 2.0.0
|
2
|
+
|
3
|
+
- Adds interactive mode (`shoot -i`);
|
4
|
+
- Increases performance by using curb (based on BrowserStack's docs);
|
5
|
+
- Activate and deactivate accepts a list of ids (instead of 1 or a range);
|
6
|
+
- Adds time elapsed for each test and for the whole suite;
|
7
|
+
- Adds update command to download all browsers again (`shoot update`);
|
8
|
+
- Allow to execute a whole folder (`shoot scenario folder/`);
|
9
|
+
|
10
|
+
# 1.1.0
|
11
|
+
|
12
|
+
- Allows to take shots inside methods, with the `shoot` method;
|
13
|
+
- Changes the folder structure it saves screenshots. Now it is `.screenshots/BROWSER/CLASS/METHOD/SHOT.png`, where SHOT is the param passed to shoot, or `finish` – taken in the end of the method – or `failed`, taken when the method fails (it helps debugging);
|
14
|
+
- Improves a lot the visual output of executions;
|
15
|
+
|
16
|
+
# 1.0.0
|
17
|
+
|
18
|
+
- Adds `test` command, allowing to run all scenarios locally against phantomjs (poltergeist);
|
19
|
+
- Adds minimally decent error treatment: if something fails doesn't stop all execution, only specific test;
|
20
|
+
- Adds `open` command, to open all screenshots (Mac only);
|
21
|
+
- Adds version commands (`version`, `-v` or `--v`);
|
data/lib/shoot/cli.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'thor'
|
2
2
|
require 'json'
|
3
|
-
require '
|
3
|
+
require 'highline/import'
|
4
4
|
|
5
5
|
module Shoot
|
6
6
|
class CLI < Thor
|
@@ -8,12 +8,42 @@ module Shoot
|
|
8
8
|
FileUtils::mkdir_p '.screenshots'
|
9
9
|
BROWSERS_PATH = '.screenshots/.browsers.json'
|
10
10
|
map %w[--version -v] => :version
|
11
|
+
map %w[--interactive -i] => :interactive
|
11
12
|
|
12
13
|
desc 'version, --version, -v', 'Shoot version'
|
13
14
|
def version
|
14
15
|
puts Shoot::VERSION
|
15
16
|
end
|
16
17
|
|
18
|
+
desc 'interactive, --interactive, -i', 'Activate one platform, based on ID or interval'
|
19
|
+
def interactive
|
20
|
+
@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
|
+
while ! @exit
|
36
|
+
choose do |menu|
|
37
|
+
menu.layout = :menu_only
|
38
|
+
menu.shell = true
|
39
|
+
|
40
|
+
available_commands.each do |command_name, command_action|
|
41
|
+
menu.choice(command_name, desc(command_name)){|_, details| command_action.call(details) }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
17
47
|
desc 'open', 'Opens all screenshots taken'
|
18
48
|
def open
|
19
49
|
open_all_screenshots
|
@@ -29,31 +59,37 @@ module Shoot
|
|
29
59
|
table _active
|
30
60
|
end
|
31
61
|
|
32
|
-
desc 'scenario', 'Runs the given scenario
|
33
|
-
def scenario(
|
34
|
-
|
35
|
-
|
62
|
+
desc 'scenario', 'Runs the given scenario or all files in a directory on all active platforms'
|
63
|
+
def scenario(path)
|
64
|
+
files = File.directory?(path) ? Dir.glob("#{path}/*.rb") : [path]
|
65
|
+
|
66
|
+
elapsed_time do
|
67
|
+
_active.each do |config|
|
68
|
+
files.each do |file|
|
69
|
+
run file, config
|
70
|
+
end
|
71
|
+
end
|
72
|
+
print set_color("\nAll tests finished", :blue)
|
73
|
+
end
|
36
74
|
end
|
37
75
|
|
38
76
|
desc 'test', 'Runs the given scenario or all files in a directory on a local phantomjs'
|
39
77
|
def test(path)
|
40
78
|
files = File.directory?(path) ? Dir.glob("#{path}/*.rb") : [path]
|
41
|
-
|
79
|
+
elapsed_time do
|
80
|
+
files.each{|file| run file, nil }
|
81
|
+
print set_color("\nAll tests finished", :blue)
|
82
|
+
end
|
42
83
|
end
|
43
84
|
|
44
|
-
desc 'activate', 'Activate
|
45
|
-
def activate(
|
46
|
-
ids
|
47
|
-
ids.each { |id| json[id]['active'] = true }
|
48
|
-
save_json
|
49
|
-
table json[from_id.to_i - 2, ids.size + 4]
|
85
|
+
desc 'activate ID', 'Activate platforms, based on IDs'
|
86
|
+
def activate(*ids)
|
87
|
+
_activate(ids)
|
50
88
|
end
|
51
89
|
|
52
|
-
desc 'deactivate', 'Deactivate
|
53
|
-
def deactivate(
|
54
|
-
|
55
|
-
save_json
|
56
|
-
table json[id.to_i - 2, 5]
|
90
|
+
desc 'deactivate', 'Deactivate platforms, based on IDs'
|
91
|
+
def deactivate(*ids)
|
92
|
+
_deactivate(ids)
|
57
93
|
end
|
58
94
|
|
59
95
|
desc 'deactivate_all', 'Deactivate all the platforms'
|
@@ -64,25 +100,60 @@ module Shoot
|
|
64
100
|
save_json
|
65
101
|
end
|
66
102
|
|
103
|
+
desc 'update', 'Update browser list (WARNING: will override active browsers)'
|
104
|
+
def update
|
105
|
+
update_json
|
106
|
+
list
|
107
|
+
end
|
108
|
+
|
67
109
|
no_commands do
|
110
|
+
def elapsed_time
|
111
|
+
require 'benchmark'
|
112
|
+
|
113
|
+
elapsed_time = Benchmark.measure do
|
114
|
+
yield
|
115
|
+
end
|
116
|
+
print set_color " (#{elapsed_time.real.to_i}s)\n", :blue
|
117
|
+
end
|
118
|
+
|
119
|
+
def desc(command)
|
120
|
+
CLI.commands[command.to_s].description rescue nil
|
121
|
+
end
|
122
|
+
|
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
|
+
|
68
139
|
def open_all_screenshots
|
69
140
|
`open #{Dir.glob(".screenshots/**/*.png").join(" ")}`
|
70
141
|
end
|
71
142
|
|
72
|
-
def run(file, config=nil)
|
143
|
+
def run(file, config = nil)
|
73
144
|
klass = get_const_from_file(file)
|
74
145
|
instance = klass.new(config)
|
75
146
|
puts set_color instance.platform_name, :white, :bold
|
76
147
|
klass.instance_methods(false).each do |method|
|
77
148
|
print set_color " ➥ #{klass}##{method} ... ", :white, :bold
|
149
|
+
error = nil
|
78
150
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
print set_color "FAILED\n", :red
|
84
|
-
puts set_color " ⚠ #{error}", :red
|
151
|
+
elapsed_time do
|
152
|
+
ok, error = instance.run(method)
|
153
|
+
|
154
|
+
print ok ? set_color("OK", :green) : set_color("FAILED", :red)
|
85
155
|
end
|
156
|
+
puts set_color " ⚠ #{error}", :red if error
|
86
157
|
end
|
87
158
|
instance.ok
|
88
159
|
end
|
@@ -110,15 +181,19 @@ module Shoot
|
|
110
181
|
|
111
182
|
def to_row(p)
|
112
183
|
[
|
113
|
-
p['id'].to_s
|
184
|
+
set_color(p['id'].to_s, p['active'] ? :green : :red),
|
114
185
|
"#{p['os']} #{p['os_version']}",
|
115
186
|
"#{p['browser']} #{p['browser_version']}",
|
116
187
|
p['device']
|
117
188
|
]
|
118
189
|
end
|
119
190
|
|
191
|
+
def update_json
|
192
|
+
File.write(BROWSERS_PATH, JSON.dump(fetch_json_and_prepare))
|
193
|
+
end
|
194
|
+
|
120
195
|
def json
|
121
|
-
|
196
|
+
update_json unless File.exist?(BROWSERS_PATH)
|
122
197
|
@json ||= JSON.parse(File.read(BROWSERS_PATH))
|
123
198
|
end
|
124
199
|
|
data/lib/shoot/scenario.rb
CHANGED
@@ -2,6 +2,25 @@ require 'selenium-webdriver'
|
|
2
2
|
require 'capybara'
|
3
3
|
require 'timeout'
|
4
4
|
|
5
|
+
require 'selenium/webdriver/remote/http/curb'
|
6
|
+
|
7
|
+
module Selenium
|
8
|
+
module WebDriver
|
9
|
+
module Remote
|
10
|
+
class Bridge
|
11
|
+
attr_accessor :http_curb
|
12
|
+
def http
|
13
|
+
unless @http_curb
|
14
|
+
@http_curb = Http::Curb.new
|
15
|
+
@http_curb.server_url = @http.send(:server_url)
|
16
|
+
end
|
17
|
+
@http_curb
|
18
|
+
end
|
19
|
+
end # Bridge
|
20
|
+
end # Remote
|
21
|
+
end # WebDriver
|
22
|
+
end # Selenium
|
23
|
+
|
5
24
|
class Shoot::Scenario
|
6
25
|
URL = sprintf 'http://%s:%s@hub.browserstack.com/wd/hub',
|
7
26
|
ENV['BROWSERSTACK_USER'],
|
data/lib/shoot/version.rb
CHANGED
data/shoot.gemspec
CHANGED
@@ -25,7 +25,8 @@ Gem::Specification.new do |spec|
|
|
25
25
|
spec.add_dependency "selenium-webdriver", "~> 2"
|
26
26
|
spec.add_dependency "capybara", "~> 2"
|
27
27
|
spec.add_dependency "thor", "~> 0.19"
|
28
|
-
spec.add_dependency "colorize", "~> 0.7"
|
29
28
|
spec.add_dependency "rest-client", "~> 1.7"
|
30
29
|
spec.add_dependency "poltergeist", "~> 1.6"
|
30
|
+
spec.add_dependency "highline", "~> 1.7"
|
31
|
+
spec.add_dependency "curb", "~> 0.8.8"
|
31
32
|
end
|
data/spec/cli_spec.rb
CHANGED
@@ -89,8 +89,9 @@ describe 'Shoot::CLI' do
|
|
89
89
|
|
90
90
|
it 'runs scenario' do
|
91
91
|
cli.scenario('foo.rb')
|
92
|
-
expect(cli).to have_received(:run)
|
92
|
+
expect(cli).to have_received(:run).with("foo.rb", "foo")
|
93
93
|
end
|
94
|
+
|
94
95
|
end
|
95
96
|
|
96
97
|
describe 'test' do
|
@@ -101,7 +102,7 @@ describe 'Shoot::CLI' do
|
|
101
102
|
|
102
103
|
it 'runs scenario' do
|
103
104
|
cli.test('foo.rb')
|
104
|
-
expect(cli).to have_received(:run).with("foo.rb")
|
105
|
+
expect(cli).to have_received(:run).with("foo.rb", nil)
|
105
106
|
end
|
106
107
|
end
|
107
108
|
|
@@ -114,8 +115,8 @@ describe 'Shoot::CLI' do
|
|
114
115
|
|
115
116
|
it 'runs scenario' do
|
116
117
|
cli.test('foo')
|
117
|
-
expect(cli).to have_received(:run).with("foo/bar.rb")
|
118
|
-
expect(cli).to have_received(:run).with("foo/baz.rb")
|
118
|
+
expect(cli).to have_received(:run).with("foo/bar.rb", nil)
|
119
|
+
expect(cli).to have_received(:run).with("foo/baz.rb", nil)
|
119
120
|
end
|
120
121
|
end
|
121
122
|
end
|
@@ -126,15 +127,15 @@ describe 'Shoot::CLI' do
|
|
126
127
|
def initialize(config); end
|
127
128
|
def method; end
|
128
129
|
end
|
129
|
-
|
130
|
-
allow_any_instance_of(Foo).to receive(:
|
130
|
+
allow_any_instance_of(Foo).to receive(:run).and_return([true, ""])
|
131
|
+
allow_any_instance_of(Foo).to receive(:platform_name)
|
131
132
|
expect_any_instance_of(Foo).to receive(:ok)
|
132
133
|
|
133
134
|
allow(cli).to receive(:get_const_from_file).with("foo.rb").and_return(Foo)
|
134
135
|
end
|
135
136
|
|
136
137
|
it 'runs scenario' do
|
137
|
-
cli.run('foo.rb', foo: :bar)
|
138
|
+
cli.run('foo.rb', {foo: :bar})
|
138
139
|
end
|
139
140
|
end
|
140
141
|
|
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:
|
4
|
+
version: 2.0.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-
|
11
|
+
date: 2015-05-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -95,21 +95,35 @@ dependencies:
|
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0.19'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
98
|
+
name: rest-client
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
101
|
- - "~>"
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version: '
|
103
|
+
version: '1.7'
|
104
104
|
type: :runtime
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
108
|
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version: '
|
110
|
+
version: '1.7'
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
|
-
name:
|
112
|
+
name: poltergeist
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '1.6'
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '1.6'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: highline
|
113
127
|
requirement: !ruby/object:Gem::Requirement
|
114
128
|
requirements:
|
115
129
|
- - "~>"
|
@@ -123,19 +137,19 @@ dependencies:
|
|
123
137
|
- !ruby/object:Gem::Version
|
124
138
|
version: '1.7'
|
125
139
|
- !ruby/object:Gem::Dependency
|
126
|
-
name:
|
140
|
+
name: curb
|
127
141
|
requirement: !ruby/object:Gem::Requirement
|
128
142
|
requirements:
|
129
143
|
- - "~>"
|
130
144
|
- !ruby/object:Gem::Version
|
131
|
-
version:
|
145
|
+
version: 0.8.8
|
132
146
|
type: :runtime
|
133
147
|
prerelease: false
|
134
148
|
version_requirements: !ruby/object:Gem::Requirement
|
135
149
|
requirements:
|
136
150
|
- - "~>"
|
137
151
|
- !ruby/object:Gem::Version
|
138
|
-
version:
|
152
|
+
version: 0.8.8
|
139
153
|
description: A helper to take shots on BrowserStack. Run the shoot binary for more
|
140
154
|
info.
|
141
155
|
email:
|
@@ -146,6 +160,7 @@ extensions: []
|
|
146
160
|
extra_rdoc_files: []
|
147
161
|
files:
|
148
162
|
- ".gitignore"
|
163
|
+
- Changelog.md
|
149
164
|
- Gemfile
|
150
165
|
- LICENSE
|
151
166
|
- LICENSE.txt
|