turbot 0.1.34 → 0.1.35
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +6 -0
- data/lib/turbot/auth.rb +1 -1
- data/lib/turbot/cli.rb +4 -0
- data/lib/turbot/command/bots.rb +17 -15
- data/lib/turbot/version.rb +1 -1
- data/spec/schemas/{dummy_schema.json → dummy-schema.json} +0 -0
- data/spec/spec_helper.rb +8 -1
- data/spec/turbot/auth_spec.rb +75 -75
- data/spec/turbot/client/ssl_endpoint_spec.rb +6 -6
- data/spec/turbot/client_spec.rb +4 -4
- data/spec/turbot/command/bots_spec.rb +50 -24
- metadata +151 -8
data/README.md
CHANGED
@@ -1,6 +1,12 @@
|
|
1
1
|
Turbot CLI
|
2
2
|
==========
|
3
3
|
|
4
|
+
[![Gem Version](https://badge.fury.io/rb/turbot.svg)](https://badge.fury.io/rb/turbot)
|
5
|
+
[![Build Status](https://secure.travis-ci.org/openc/turbot-client.png)](https://travis-ci.org/openc/turbot-client)
|
6
|
+
[![Dependency Status](https://gemnasium.com/openc/turbot-client.png)](https://gemnasium.com/openc/turbot-client)
|
7
|
+
[![Coverage Status](https://coveralls.io/repos/openc/turbot-client/badge.png)](https://coveralls.io/r/openc/turbot-client)
|
8
|
+
[![Code Climate](https://codeclimate.com/github/openc/turbot-client.png)](https://codeclimate.com/github/openc/turbot-client)
|
9
|
+
|
4
10
|
The Turbot CLI is used to manage Turbot apps from the command line.
|
5
11
|
|
6
12
|
Setup
|
data/lib/turbot/auth.rb
CHANGED
@@ -197,7 +197,7 @@ class Turbot::Auth
|
|
197
197
|
# write these to a hidden file
|
198
198
|
write_credentials
|
199
199
|
check
|
200
|
-
rescue Turbot::API::Errors::NotFound, Turbot::API::Errors::Unauthorized => e
|
200
|
+
rescue RestClient::Unauthorized, Turbot::API::Errors::NotFound, Turbot::API::Errors::Unauthorized => e
|
201
201
|
delete_credentials
|
202
202
|
display "Authentication failed."
|
203
203
|
retry if retry_login?
|
data/lib/turbot/cli.rb
CHANGED
data/lib/turbot/command/bots.rb
CHANGED
@@ -151,8 +151,7 @@ class Turbot::Command::Bots < Turbot::Command::Base
|
|
151
151
|
error("There's already a bot called #{bot} registered with Turbot. Bot names must be unique.")
|
152
152
|
end
|
153
153
|
|
154
|
-
|
155
|
-
manifest = parsed_manifest(working_dir)
|
154
|
+
manifest = parsed_manifest(working_directory)
|
156
155
|
response = api.create_bot(bot, manifest)
|
157
156
|
if response.is_a? Turbot::API::FailureResponse
|
158
157
|
error(response.message)
|
@@ -174,11 +173,10 @@ class Turbot::Command::Bots < Turbot::Command::Base
|
|
174
173
|
puts "Are you happy your bot produces valid data (e.g. with `turbot bots:validate`)? [Y/n]"
|
175
174
|
confirmed = ask
|
176
175
|
error("Aborting push") if !confirmed.downcase.empty? && confirmed.downcase != "y"
|
177
|
-
|
178
|
-
manifest = parsed_manifest(working_dir)
|
176
|
+
manifest = parsed_manifest(working_directory)
|
179
177
|
archive = Tempfile.new(bot)
|
180
178
|
archive_path = "#{archive.path}.zip"
|
181
|
-
create_zip_archive(archive_path,
|
179
|
+
create_zip_archive(archive_path, working_directory, manifest['files'] + ['manifest.json'])
|
182
180
|
|
183
181
|
response = File.open(archive_path) {|file| api.update_code(bot, file)}
|
184
182
|
case response
|
@@ -199,18 +197,18 @@ class Turbot::Command::Bots < Turbot::Command::Base
|
|
199
197
|
# Validating example... done
|
200
198
|
|
201
199
|
def validate
|
202
|
-
scraper_path = shift_argument || scraper_file(
|
200
|
+
scraper_path = shift_argument || scraper_file(working_directory)
|
203
201
|
validate_arguments!
|
204
|
-
config = parsed_manifest(
|
202
|
+
config = parsed_manifest(working_directory)
|
205
203
|
|
206
|
-
%w(bot_id data_type identifying_fields files publisher).each do |key|
|
204
|
+
%w(bot_id data_type identifying_fields files language publisher).each do |key|
|
207
205
|
error("Manifest is missing #{key}") unless config.has_key?(key)
|
208
206
|
end
|
209
207
|
|
210
208
|
type = config["data_type"]
|
211
209
|
|
212
210
|
handler = ValidationHandler.new
|
213
|
-
runner = TurbotRunner::Runner.new(
|
211
|
+
runner = TurbotRunner::Runner.new(working_directory, :record_handler => handler)
|
214
212
|
rc = runner.run
|
215
213
|
|
216
214
|
puts
|
@@ -233,7 +231,7 @@ class Turbot::Command::Bots < Turbot::Command::Base
|
|
233
231
|
validate_arguments!
|
234
232
|
|
235
233
|
handler = DumpHandler.new
|
236
|
-
runner = TurbotRunner::Runner.new(
|
234
|
+
runner = TurbotRunner::Runner.new(working_directory, :record_handler => handler)
|
237
235
|
rc = runner.run
|
238
236
|
|
239
237
|
puts
|
@@ -255,7 +253,7 @@ class Turbot::Command::Bots < Turbot::Command::Base
|
|
255
253
|
#
|
256
254
|
# def single
|
257
255
|
# # This will need to be language-aware, eventually
|
258
|
-
# scraper_path = shift_argument || scraper_file(
|
256
|
+
# scraper_path = shift_argument || scraper_file(working_directory)
|
259
257
|
# validate_arguments!
|
260
258
|
# print 'Arguments (as JSON object, e.g. {"id":"ABC123"}: '
|
261
259
|
# arg = ask
|
@@ -276,9 +274,9 @@ class Turbot::Command::Bots < Turbot::Command::Base
|
|
276
274
|
def preview
|
277
275
|
validate_arguments!
|
278
276
|
|
279
|
-
config = parsed_manifest(
|
277
|
+
config = parsed_manifest(working_directory)
|
280
278
|
|
281
|
-
response = api.update_bot(bot, parsed_manifest(
|
279
|
+
response = api.update_bot(bot, parsed_manifest(working_directory))
|
282
280
|
if !response.is_a? Turbot::API::SuccessResponse
|
283
281
|
error(response.message)
|
284
282
|
end
|
@@ -291,7 +289,7 @@ class Turbot::Command::Bots < Turbot::Command::Base
|
|
291
289
|
puts "Sending to turbot... "
|
292
290
|
|
293
291
|
handler = PreviewHandler.new(bot, api)
|
294
|
-
runner = TurbotRunner::Runner.new(
|
292
|
+
runner = TurbotRunner::Runner.new(working_directory, :record_handler => handler)
|
295
293
|
rc = runner.run
|
296
294
|
|
297
295
|
puts
|
@@ -332,8 +330,12 @@ class Turbot::Command::Bots < Turbot::Command::Base
|
|
332
330
|
Dir.glob("scraper*").reject{|n| !n.match(/(rb|py)$/)}.first
|
333
331
|
end
|
334
332
|
|
333
|
+
def working_directory
|
334
|
+
Dir.pwd
|
335
|
+
end
|
336
|
+
|
335
337
|
def manifest_path
|
336
|
-
File.join(
|
338
|
+
File.join(working_directory, 'manifest.json')
|
337
339
|
end
|
338
340
|
|
339
341
|
def create_zip_archive(archive_path, basepath, subpaths)
|
data/lib/turbot/version.rb
CHANGED
File without changes
|
data/spec/spec_helper.rb
CHANGED
@@ -2,6 +2,13 @@ $stdin = File.new("/dev/null")
|
|
2
2
|
|
3
3
|
require "rubygems"
|
4
4
|
|
5
|
+
require "simplecov"
|
6
|
+
require "coveralls"
|
7
|
+
SimpleCov.formatter = Coveralls::SimpleCov::Formatter
|
8
|
+
SimpleCov.start do
|
9
|
+
add_filter "spec"
|
10
|
+
end
|
11
|
+
|
5
12
|
require "excon"
|
6
13
|
Excon.defaults[:mock] = true
|
7
14
|
|
@@ -30,7 +37,7 @@ def org_api
|
|
30
37
|
end
|
31
38
|
|
32
39
|
def stub_api_request(method, path)
|
33
|
-
stub_request(method, "
|
40
|
+
stub_request(method, "http://turbot.opencorporates.com#{path}")
|
34
41
|
end
|
35
42
|
|
36
43
|
def prepare_command(klass)
|
data/spec/turbot/auth_spec.rb
CHANGED
@@ -63,7 +63,7 @@ module Turbot
|
|
63
63
|
before do
|
64
64
|
@cli.stub!(:ask_for_credentials).and_return(['new_user', 'new_password'])
|
65
65
|
@cli.stub!(:check)
|
66
|
-
@cli.should_receive(:check_for_associated_ssh_key)
|
66
|
+
# @cli.should_receive(:check_for_associated_ssh_key)
|
67
67
|
@cli.reauthorize
|
68
68
|
end
|
69
69
|
it "updates saved credentials" do
|
@@ -89,7 +89,7 @@ module Turbot
|
|
89
89
|
it "asks for credentials when the file doesn't exist" do
|
90
90
|
@cli.delete_credentials
|
91
91
|
@cli.should_receive(:ask_for_credentials).and_return(["u", "p"])
|
92
|
-
@cli.should_receive(:check_for_associated_ssh_key)
|
92
|
+
# @cli.should_receive(:check_for_associated_ssh_key)
|
93
93
|
@cli.user.should == 'u'
|
94
94
|
@cli.password.should == 'p'
|
95
95
|
end
|
@@ -99,7 +99,7 @@ module Turbot
|
|
99
99
|
@cli.stub!(:check)
|
100
100
|
@cli.stub!(:ask_for_credentials).and_return("username", "apikey")
|
101
101
|
@cli.should_receive(:write_credentials)
|
102
|
-
@cli.should_receive(:check_for_associated_ssh_key)
|
102
|
+
# @cli.should_receive(:check_for_associated_ssh_key)
|
103
103
|
@cli.ask_for_and_save_credentials
|
104
104
|
end
|
105
105
|
|
@@ -107,7 +107,7 @@ module Turbot
|
|
107
107
|
@cli.stub!(:write_credentials)
|
108
108
|
@cli.stub!(:retry_login?).and_return(false)
|
109
109
|
@cli.stub!(:ask_for_credentials).and_return("username", "apikey")
|
110
|
-
@cli.stub!(:check) { raise
|
110
|
+
@cli.stub!(:check) { raise RestClient::Unauthorized }
|
111
111
|
@cli.should_receive(:delete_credentials)
|
112
112
|
lambda { @cli.ask_for_and_save_credentials }.should raise_error(SystemExit)
|
113
113
|
end
|
@@ -117,7 +117,7 @@ module Turbot
|
|
117
117
|
@cli.stub!(:write_credentials)
|
118
118
|
@cli.stub!(:delete_credentials)
|
119
119
|
@cli.stub!(:ask_for_credentials).and_return("username", "apikey")
|
120
|
-
@cli.stub!(:check) { raise
|
120
|
+
@cli.stub!(:check) { raise RestClient::Unauthorized }
|
121
121
|
@cli.should_receive(:ask_for_credentials).exactly(3).times
|
122
122
|
lambda { @cli.ask_for_and_save_credentials }.should raise_error(SystemExit)
|
123
123
|
end
|
@@ -125,7 +125,7 @@ module Turbot
|
|
125
125
|
it "writes the login information to the credentials file for the 'turbot login' command" do
|
126
126
|
@cli.stub!(:ask_for_credentials).and_return(['one', 'two'])
|
127
127
|
@cli.stub!(:check)
|
128
|
-
@cli.should_receive(:check_for_associated_ssh_key)
|
128
|
+
# @cli.should_receive(:check_for_associated_ssh_key)
|
129
129
|
@cli.reauthorize
|
130
130
|
Netrc.read(@cli.netrc_path)["api.#{@cli.host}"].should == (['one', 'two'])
|
131
131
|
end
|
@@ -141,74 +141,74 @@ module Turbot
|
|
141
141
|
end
|
142
142
|
end
|
143
143
|
|
144
|
-
describe "automatic key uploading" do
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
end
|
144
|
+
# describe "automatic key uploading" do
|
145
|
+
# before(:each) do
|
146
|
+
# FileUtils.mkdir_p("#{@cli.home_directory}/.ssh")
|
147
|
+
# @cli.stub!(:ask_for_credentials).and_return("username", "apikey")
|
148
|
+
# end
|
149
|
+
|
150
|
+
# describe "an account with existing keys" do
|
151
|
+
# before :each do
|
152
|
+
# @api = mock(Object)
|
153
|
+
# @response = mock(Object)
|
154
|
+
# @response.should_receive(:body).and_return(['existingkeys'])
|
155
|
+
# @api.should_receive(:get_ssh_keys).and_return(@response)
|
156
|
+
# @cli.should_receive(:api).and_return(@api)
|
157
|
+
# end
|
158
|
+
|
159
|
+
# it "should not do anything if the account already has keys" do
|
160
|
+
# @cli.should_not_receive(:associate_key)
|
161
|
+
# @cli.check_for_associated_ssh_key
|
162
|
+
# end
|
163
|
+
# end
|
164
|
+
|
165
|
+
# describe "an account with no keys" do
|
166
|
+
# before :each do
|
167
|
+
# @api = mock(Object)
|
168
|
+
# @response = mock(Object)
|
169
|
+
# @response.should_receive(:body).and_return([])
|
170
|
+
# @api.should_receive(:get_ssh_keys).and_return(@response)
|
171
|
+
# @cli.should_receive(:api).and_return(@api)
|
172
|
+
# end
|
173
|
+
|
174
|
+
# describe "with zero public keys" do
|
175
|
+
# it "should ask to generate a key" do
|
176
|
+
# @cli.should_receive(:ask).and_return("y")
|
177
|
+
# @cli.should_receive(:generate_ssh_key).with("id_rsa")
|
178
|
+
# @cli.should_receive(:associate_key).with("#{@cli.home_directory}/.ssh/id_rsa.pub")
|
179
|
+
# @cli.check_for_associated_ssh_key
|
180
|
+
# end
|
181
|
+
# end
|
182
|
+
|
183
|
+
# describe "with one public key" do
|
184
|
+
# before(:each) { FileUtils.touch("#{@cli.home_directory}/.ssh/id_rsa.pub") }
|
185
|
+
# after(:each) { FileUtils.rm("#{@cli.home_directory}/.ssh/id_rsa.pub") }
|
186
|
+
|
187
|
+
# it "should upload the key" do
|
188
|
+
# @cli.should_receive(:associate_key).with("#{@cli.home_directory}/.ssh/id_rsa.pub")
|
189
|
+
# @cli.check_for_associated_ssh_key
|
190
|
+
# end
|
191
|
+
# end
|
192
|
+
|
193
|
+
# describe "with many public keys" do
|
194
|
+
# before(:each) do
|
195
|
+
# FileUtils.touch("#{@cli.home_directory}/.ssh/id_rsa.pub")
|
196
|
+
# FileUtils.touch("#{@cli.home_directory}/.ssh/id_rsa2.pub")
|
197
|
+
# end
|
198
|
+
|
199
|
+
# after(:each) do
|
200
|
+
# FileUtils.rm("#{@cli.home_directory}/.ssh/id_rsa.pub")
|
201
|
+
# FileUtils.rm("#{@cli.home_directory}/.ssh/id_rsa2.pub")
|
202
|
+
# end
|
203
|
+
|
204
|
+
# it "should ask which key to upload" do
|
205
|
+
# File.open("#{@cli.home_directory}/.ssh/id_rsa.pub", "w") { |f| f.puts }
|
206
|
+
# @cli.should_receive(:associate_key).with("#{@cli.home_directory}/.ssh/id_rsa2.pub")
|
207
|
+
# @cli.should_receive(:ask).and_return("2")
|
208
|
+
# @cli.check_for_associated_ssh_key
|
209
|
+
# end
|
210
|
+
# end
|
211
|
+
# end
|
212
|
+
# end
|
213
213
|
end
|
214
214
|
end
|
@@ -7,20 +7,20 @@ describe Turbot::Client, "ssl endpoints" do
|
|
7
7
|
end
|
8
8
|
|
9
9
|
it "adds an ssl endpoint" do
|
10
|
-
stub_request(:post, "
|
10
|
+
stub_request(:post, "http://turbot.opencorporates.com/bots/example/ssl-endpoints").
|
11
11
|
with(:body => { :accept => "json", :pem => "pem content", :key => "key content" }).
|
12
12
|
to_return(:body => %{ {"cname": "tokyo-1050" } })
|
13
13
|
@client.ssl_endpoint_add("example", "pem content", "key content").should == { "cname" => "tokyo-1050" }
|
14
14
|
end
|
15
15
|
|
16
16
|
it "gets info on an ssl endpoint" do
|
17
|
-
stub_request(:get, "
|
17
|
+
stub_request(:get, "http://turbot.opencorporates.com/bots/example/ssl-endpoints/tokyo-1050").
|
18
18
|
to_return(:body => %{ {"cname": "tokyo-1050" } })
|
19
19
|
@client.ssl_endpoint_info("example", "tokyo-1050").should == { "cname" => "tokyo-1050" }
|
20
20
|
end
|
21
21
|
|
22
22
|
it "lists ssl endpoints for an bot" do
|
23
|
-
stub_request(:get, "
|
23
|
+
stub_request(:get, "http://turbot.opencorporates.com/bots/example/ssl-endpoints").
|
24
24
|
to_return(:body => %{ [{"cname": "tokyo-1050" }, {"cname": "tokyo-1051" }] })
|
25
25
|
@client.ssl_endpoint_list("example").should == [
|
26
26
|
{ "cname" => "tokyo-1050" },
|
@@ -29,18 +29,18 @@ describe Turbot::Client, "ssl endpoints" do
|
|
29
29
|
end
|
30
30
|
|
31
31
|
it "removes an ssl endpoint" do
|
32
|
-
stub_request(:delete, "
|
32
|
+
stub_request(:delete, "http://turbot.opencorporates.com/bots/example/ssl-endpoints/tokyo-1050")
|
33
33
|
@client.ssl_endpoint_remove("example", "tokyo-1050")
|
34
34
|
end
|
35
35
|
|
36
36
|
it "rolls back an ssl endpoint" do
|
37
|
-
stub_request(:post, "
|
37
|
+
stub_request(:post, "http://turbot.opencorporates.com/bots/example/ssl-endpoints/tokyo-1050/rollback").
|
38
38
|
to_return(:body => %{ {"cname": "tokyo-1050" } })
|
39
39
|
@client.ssl_endpoint_rollback("example", "tokyo-1050").should == { "cname" => "tokyo-1050" }
|
40
40
|
end
|
41
41
|
|
42
42
|
it "updates an ssl endpoint" do
|
43
|
-
stub_request(:put, "
|
43
|
+
stub_request(:put, "http://turbot.opencorporates.com/bots/example/ssl-endpoints/tokyo-1050").
|
44
44
|
with(:body => { :accept => "json", :pem => "pem content", :key => "key content" }).
|
45
45
|
to_return(:body => %{ {"cname": "tokyo-1050" } })
|
46
46
|
@client.ssl_endpoint_update("example", "tokyo-1050", "pem content", "key content").should == { "cname" => "tokyo-1050" }
|
data/spec/turbot/client_spec.rb
CHANGED
@@ -14,7 +14,7 @@ describe Turbot::Client do
|
|
14
14
|
|
15
15
|
it "Client.auth -> get user details" do
|
16
16
|
user_info = { "api_key" => "abc" }
|
17
|
-
stub_request(:post, "
|
17
|
+
stub_request(:post, "http://foo:bar@turbot.opencorporates.com/login").to_return(:body => json_encode(user_info))
|
18
18
|
capture_stderr do # capture deprecation message
|
19
19
|
Turbot::Client.auth("foo", "bar").should == user_info
|
20
20
|
end
|
@@ -450,7 +450,7 @@ describe Turbot::Client do
|
|
450
450
|
end
|
451
451
|
|
452
452
|
it "install_addon(bot_name, addon_name) with response" do
|
453
|
-
stub_request(:post, "
|
453
|
+
stub_request(:post, "http://turbot.opencorporates.com/bots/example/addons/addon1").
|
454
454
|
to_return(:body => json_encode({'price' => 'free', 'message' => "Don't Panic"}))
|
455
455
|
|
456
456
|
@client.install_addon('example', 'addon1').
|
@@ -458,7 +458,7 @@ describe Turbot::Client do
|
|
458
458
|
end
|
459
459
|
|
460
460
|
it "upgrade_addon(bot_name, addon_name) with response" do
|
461
|
-
stub_request(:put, "
|
461
|
+
stub_request(:put, "http://turbot.opencorporates.com/bots/example/addons/addon1").
|
462
462
|
to_return(:body => json_encode('price' => 'free', 'message' => "Don't Panic"))
|
463
463
|
|
464
464
|
@client.upgrade_addon('example', 'addon1').
|
@@ -466,7 +466,7 @@ describe Turbot::Client do
|
|
466
466
|
end
|
467
467
|
|
468
468
|
it "downgrade_addon(bot_name, addon_name) with response" do
|
469
|
-
stub_request(:put, "
|
469
|
+
stub_request(:put, "http://turbot.opencorporates.com/bots/example/addons/addon1").
|
470
470
|
to_return(:body => json_encode('price' => 'free', 'message' => "Don't Panic"))
|
471
471
|
|
472
472
|
@client.downgrade_addon('example', 'addon1').
|
@@ -3,70 +3,96 @@ require "turbot/command/bots"
|
|
3
3
|
|
4
4
|
describe Turbot::Command::Bots do
|
5
5
|
describe "validate" do
|
6
|
+
let :working_directory do
|
7
|
+
Dir.mktmpdir
|
8
|
+
end
|
9
|
+
|
10
|
+
let :schemas_directory do
|
11
|
+
Dir.mktmpdir
|
12
|
+
end
|
13
|
+
|
6
14
|
before do
|
7
15
|
config = {
|
8
16
|
'bot_id' => 'dummy bot',
|
9
17
|
'data_type' => 'dummy',
|
10
18
|
'identifying_fields' => ['name'],
|
11
19
|
'files' => 'scraper.rb',
|
20
|
+
'language' => 'ruby',
|
21
|
+
'publisher' => {
|
22
|
+
'name' => 'Dummy',
|
23
|
+
'url' => 'http://example.com/',
|
24
|
+
'terms' => 'MIT',
|
25
|
+
'terms_url' => 'http://opensource.org/licenses/MIT',
|
26
|
+
},
|
12
27
|
}
|
13
28
|
Turbot::Command::Bots.any_instance.stub(:parsed_manifest).and_return(config)
|
29
|
+
|
30
|
+
# Create a manifest.json file for TurbotRunner to find.
|
31
|
+
File.open(File.join(working_directory, 'manifest.json'), 'w') { |f| f << JSON.dump(config) }
|
32
|
+
Turbot::Command::Bots.any_instance.stub(:working_directory).and_return(working_directory)
|
33
|
+
|
34
|
+
# Change the path to TurbotRunner's schemas.
|
35
|
+
begin
|
36
|
+
old_verbose, $VERBOSE = $VERBOSE, nil
|
37
|
+
TurbotRunner::SCHEMAS_PATH = File.expand_path('../../../schemas', __FILE__)
|
38
|
+
ensure
|
39
|
+
$VERBOSE = old_verbose
|
40
|
+
end
|
14
41
|
end
|
15
42
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
and_return(File.expand_path('../../../schemas/dummy_schema.json', __FILE__))
|
43
|
+
after do
|
44
|
+
FileUtils.remove_entry_secure(working_directory)
|
45
|
+
FileUtils.remove_entry_secure(schemas_directory)
|
46
|
+
end
|
21
47
|
|
48
|
+
def define_scraper(hash)
|
49
|
+
File.open(File.join(working_directory, 'scraper.rb'), 'w') do |f|
|
50
|
+
f << <<-EOL
|
51
|
+
require 'json'
|
52
|
+
puts JSON.dump(#{hash})
|
53
|
+
EOL
|
22
54
|
end
|
55
|
+
end
|
23
56
|
|
57
|
+
context "for data_type with schema" do
|
24
58
|
it "says bot is valid if its output matches the schema" do
|
25
|
-
|
26
|
-
stub(:run_scraper_each_line).
|
27
|
-
and_yield({name: 'One'}.to_json)
|
59
|
+
define_scraper(name: 'One')
|
28
60
|
|
29
61
|
stderr, stdout = execute("bots:validate")
|
30
62
|
|
63
|
+
stdout.should include 'Validated 1 records!'
|
31
64
|
stderr.should == ""
|
32
|
-
stdout.should include 'Validated 1 records successfully'
|
33
65
|
end
|
34
66
|
|
35
67
|
it "says bot is invalid if its output doesn't match the schema" do
|
36
|
-
|
37
|
-
stub(:run_scraper_each_line).
|
38
|
-
and_yield({name: 123}.to_json)
|
68
|
+
define_scraper(name: 123)
|
39
69
|
|
40
70
|
stderr, stdout = execute("bots:validate")
|
41
71
|
|
42
|
-
stdout.should
|
43
|
-
stderr.should
|
72
|
+
stdout.should include 'Property of wrong type'
|
73
|
+
stderr.should == ""
|
44
74
|
end
|
45
75
|
|
46
76
|
context "for bot that doesn't output identifying fields" do
|
47
77
|
it "says bot is invalid" do
|
48
|
-
|
49
|
-
stub(:run_scraper_each_line).
|
50
|
-
and_yield({title: 'One'}.to_json)
|
78
|
+
define_scraper(title: 'One')
|
51
79
|
|
52
80
|
stderr, stdout = execute("bots:validate")
|
53
81
|
|
54
|
-
stdout.should
|
55
|
-
stderr.should
|
82
|
+
stdout.should include 'There were no values provided for any of the identifying fields'
|
83
|
+
stderr.should == ""
|
56
84
|
end
|
57
85
|
end
|
58
86
|
end
|
59
87
|
|
60
88
|
context "for data_type without schema" do
|
61
89
|
it "says bot is invalid" do
|
62
|
-
|
63
|
-
stub(:get_schema).
|
64
|
-
and_return(nil)
|
90
|
+
define_scraper({})
|
65
91
|
|
66
92
|
stderr, stdout = execute("bots:validate")
|
67
93
|
|
68
|
-
stdout.should
|
69
|
-
stderr.should
|
94
|
+
stdout.should include "Validated 0 records before bot failed!"
|
95
|
+
stderr.should == ""
|
70
96
|
end
|
71
97
|
end
|
72
98
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: turbot
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.35
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2016-01-05 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: turbotlib
|
@@ -130,7 +130,7 @@ dependencies:
|
|
130
130
|
requirements:
|
131
131
|
- - '='
|
132
132
|
- !ruby/object:Gem::Version
|
133
|
-
version: 0.2.
|
133
|
+
version: 0.2.7
|
134
134
|
type: :runtime
|
135
135
|
prerelease: false
|
136
136
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -138,7 +138,7 @@ dependencies:
|
|
138
138
|
requirements:
|
139
139
|
- - '='
|
140
140
|
- !ruby/object:Gem::Version
|
141
|
-
version: 0.2.
|
141
|
+
version: 0.2.7
|
142
142
|
- !ruby/object:Gem::Dependency
|
143
143
|
name: excon
|
144
144
|
requirement: !ruby/object:Gem::Requirement
|
@@ -155,8 +155,152 @@ dependencies:
|
|
155
155
|
- - ! '>='
|
156
156
|
- !ruby/object:Gem::Version
|
157
157
|
version: '0'
|
158
|
+
- !ruby/object:Gem::Dependency
|
159
|
+
name: coveralls
|
160
|
+
requirement: !ruby/object:Gem::Requirement
|
161
|
+
none: false
|
162
|
+
requirements:
|
163
|
+
- - ! '>='
|
164
|
+
- !ruby/object:Gem::Version
|
165
|
+
version: '0'
|
166
|
+
type: :development
|
167
|
+
prerelease: false
|
168
|
+
version_requirements: !ruby/object:Gem::Requirement
|
169
|
+
none: false
|
170
|
+
requirements:
|
171
|
+
- - ! '>='
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
174
|
+
- !ruby/object:Gem::Dependency
|
175
|
+
name: fakefs
|
176
|
+
requirement: !ruby/object:Gem::Requirement
|
177
|
+
none: false
|
178
|
+
requirements:
|
179
|
+
- - ! '>='
|
180
|
+
- !ruby/object:Gem::Version
|
181
|
+
version: '0'
|
182
|
+
type: :development
|
183
|
+
prerelease: false
|
184
|
+
version_requirements: !ruby/object:Gem::Requirement
|
185
|
+
none: false
|
186
|
+
requirements:
|
187
|
+
- - ! '>='
|
188
|
+
- !ruby/object:Gem::Version
|
189
|
+
version: '0'
|
190
|
+
- !ruby/object:Gem::Dependency
|
191
|
+
name: json
|
192
|
+
requirement: !ruby/object:Gem::Requirement
|
193
|
+
none: false
|
194
|
+
requirements:
|
195
|
+
- - ! '>='
|
196
|
+
- !ruby/object:Gem::Version
|
197
|
+
version: '0'
|
198
|
+
type: :development
|
199
|
+
prerelease: false
|
200
|
+
version_requirements: !ruby/object:Gem::Requirement
|
201
|
+
none: false
|
202
|
+
requirements:
|
203
|
+
- - ! '>='
|
204
|
+
- !ruby/object:Gem::Version
|
205
|
+
version: '0'
|
206
|
+
- !ruby/object:Gem::Dependency
|
207
|
+
name: rake
|
208
|
+
requirement: !ruby/object:Gem::Requirement
|
209
|
+
none: false
|
210
|
+
requirements:
|
211
|
+
- - ! '>='
|
212
|
+
- !ruby/object:Gem::Version
|
213
|
+
version: 0.8.7
|
214
|
+
type: :development
|
215
|
+
prerelease: false
|
216
|
+
version_requirements: !ruby/object:Gem::Requirement
|
217
|
+
none: false
|
218
|
+
requirements:
|
219
|
+
- - ! '>='
|
220
|
+
- !ruby/object:Gem::Version
|
221
|
+
version: 0.8.7
|
222
|
+
- !ruby/object:Gem::Dependency
|
223
|
+
name: rr
|
224
|
+
requirement: !ruby/object:Gem::Requirement
|
225
|
+
none: false
|
226
|
+
requirements:
|
227
|
+
- - ~>
|
228
|
+
- !ruby/object:Gem::Version
|
229
|
+
version: 1.0.2
|
230
|
+
type: :development
|
231
|
+
prerelease: false
|
232
|
+
version_requirements: !ruby/object:Gem::Requirement
|
233
|
+
none: false
|
234
|
+
requirements:
|
235
|
+
- - ~>
|
236
|
+
- !ruby/object:Gem::Version
|
237
|
+
version: 1.0.2
|
238
|
+
- !ruby/object:Gem::Dependency
|
239
|
+
name: rspec
|
240
|
+
requirement: !ruby/object:Gem::Requirement
|
241
|
+
none: false
|
242
|
+
requirements:
|
243
|
+
- - '='
|
244
|
+
- !ruby/object:Gem::Version
|
245
|
+
version: 2.13.0
|
246
|
+
type: :development
|
247
|
+
prerelease: false
|
248
|
+
version_requirements: !ruby/object:Gem::Requirement
|
249
|
+
none: false
|
250
|
+
requirements:
|
251
|
+
- - '='
|
252
|
+
- !ruby/object:Gem::Version
|
253
|
+
version: 2.13.0
|
254
|
+
- !ruby/object:Gem::Dependency
|
255
|
+
name: sqlite3
|
256
|
+
requirement: !ruby/object:Gem::Requirement
|
257
|
+
none: false
|
258
|
+
requirements:
|
259
|
+
- - ! '>='
|
260
|
+
- !ruby/object:Gem::Version
|
261
|
+
version: '0'
|
262
|
+
type: :development
|
263
|
+
prerelease: false
|
264
|
+
version_requirements: !ruby/object:Gem::Requirement
|
265
|
+
none: false
|
266
|
+
requirements:
|
267
|
+
- - ! '>='
|
268
|
+
- !ruby/object:Gem::Version
|
269
|
+
version: '0'
|
270
|
+
- !ruby/object:Gem::Dependency
|
271
|
+
name: tins
|
272
|
+
requirement: !ruby/object:Gem::Requirement
|
273
|
+
none: false
|
274
|
+
requirements:
|
275
|
+
- - ~>
|
276
|
+
- !ruby/object:Gem::Version
|
277
|
+
version: 1.6.0
|
278
|
+
type: :development
|
279
|
+
prerelease: false
|
280
|
+
version_requirements: !ruby/object:Gem::Requirement
|
281
|
+
none: false
|
282
|
+
requirements:
|
283
|
+
- - ~>
|
284
|
+
- !ruby/object:Gem::Version
|
285
|
+
version: 1.6.0
|
286
|
+
- !ruby/object:Gem::Dependency
|
287
|
+
name: webmock
|
288
|
+
requirement: !ruby/object:Gem::Requirement
|
289
|
+
none: false
|
290
|
+
requirements:
|
291
|
+
- - ! '>='
|
292
|
+
- !ruby/object:Gem::Version
|
293
|
+
version: '0'
|
294
|
+
type: :development
|
295
|
+
prerelease: false
|
296
|
+
version_requirements: !ruby/object:Gem::Requirement
|
297
|
+
none: false
|
298
|
+
requirements:
|
299
|
+
- - ! '>='
|
300
|
+
- !ruby/object:Gem::Version
|
301
|
+
version: '0'
|
158
302
|
description: Client library and command-line tool to deploy and manage apps on Turbot.
|
159
|
-
email: support@turbot.com
|
303
|
+
email: support@turbot.opencorporates.com
|
160
304
|
executables:
|
161
305
|
- turbot
|
162
306
|
extensions: []
|
@@ -196,7 +340,7 @@ files:
|
|
196
340
|
- lib/vendor/turbot/okjson.rb
|
197
341
|
- spec/helper/legacy_help.rb
|
198
342
|
- spec/helper/pg_dump_restore_spec.rb
|
199
|
-
- spec/schemas/
|
343
|
+
- spec/schemas/dummy-schema.json
|
200
344
|
- spec/spec.opts
|
201
345
|
- spec/spec_helper.rb
|
202
346
|
- spec/support/display_message_matcher.rb
|
@@ -223,7 +367,7 @@ files:
|
|
223
367
|
- templates/manifest.json
|
224
368
|
- templates/python/scraper.py
|
225
369
|
- templates/ruby/scraper.rb
|
226
|
-
homepage:
|
370
|
+
homepage: https://turbot.opencorporates.com/
|
227
371
|
licenses:
|
228
372
|
- MIT
|
229
373
|
post_install_message:
|
@@ -249,4 +393,3 @@ signing_key:
|
|
249
393
|
specification_version: 3
|
250
394
|
summary: Client library and CLI to deploy apps on Turbot.
|
251
395
|
test_files: []
|
252
|
-
has_rdoc:
|