scrapinghub-client 0.0.1
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 +7 -0
- data/.gitignore +1 -0
- data/.rspec +3 -0
- data/.travis.yml +6 -0
- data/Gemfile +5 -0
- data/LICENSE +21 -0
- data/README.md +46 -0
- data/Rakefile +22 -0
- data/lib/scrapinghub-client.rb +3 -0
- data/lib/scrapinghub/jobs.rb +175 -0
- data/lib/scrapinghub/version.rb +3 -0
- data/scrapinghub.gemspec +26 -0
- data/spec/fixtures/vcr_cassettes/jobs/delete/bad_auth.yml +38 -0
- data/spec/fixtures/vcr_cassettes/jobs/delete/job/invalid.yml +38 -0
- data/spec/fixtures/vcr_cassettes/jobs/delete/job/multiple.yml +38 -0
- data/spec/fixtures/vcr_cassettes/jobs/delete/job/single.yml +38 -0
- data/spec/fixtures/vcr_cassettes/jobs/delete/project/invalid.yml +39 -0
- data/spec/fixtures/vcr_cassettes/jobs/delete/project/valid.yml +38 -0
- data/spec/fixtures/vcr_cassettes/jobs/list/bad_auth.yml +38 -0
- data/spec/fixtures/vcr_cassettes/jobs/list/count/3.yml +53 -0
- data/spec/fixtures/vcr_cassettes/jobs/list/has_tag/invalid.yml +38 -0
- data/spec/fixtures/vcr_cassettes/jobs/list/has_tag/multiple.yml +53 -0
- data/spec/fixtures/vcr_cassettes/jobs/list/has_tag/single.yml +48 -0
- data/spec/fixtures/vcr_cassettes/jobs/list/job/invalid.yml +38 -0
- data/spec/fixtures/vcr_cassettes/jobs/list/job/multiple.yml +48 -0
- data/spec/fixtures/vcr_cassettes/jobs/list/job/single.yml +43 -0
- data/spec/fixtures/vcr_cassettes/jobs/list/lacks_tag/invalid.yml +81 -0
- data/spec/fixtures/vcr_cassettes/jobs/list/lacks_tag/multiple.yml +67 -0
- data/spec/fixtures/vcr_cassettes/jobs/list/lacks_tag/single.yml +72 -0
- data/spec/fixtures/vcr_cassettes/jobs/list/project/invalid.yml +39 -0
- data/spec/fixtures/vcr_cassettes/jobs/list/project/valid.yml +81 -0
- data/spec/fixtures/vcr_cassettes/jobs/list/spider/invalid.yml +38 -0
- data/spec/fixtures/vcr_cassettes/jobs/list/spider/valid.yml +62 -0
- data/spec/fixtures/vcr_cassettes/jobs/list/state/finished.yml +81 -0
- data/spec/fixtures/vcr_cassettes/jobs/list/state/pending.yml +38 -0
- data/spec/fixtures/vcr_cassettes/jobs/schedule/bad_auth.yml +38 -0
- data/spec/fixtures/vcr_cassettes/jobs/schedule/project/invalid.yml +39 -0
- data/spec/fixtures/vcr_cassettes/jobs/schedule/spider/add_tag.yml +38 -0
- data/spec/fixtures/vcr_cassettes/jobs/schedule/spider/already-running.yml +39 -0
- data/spec/fixtures/vcr_cassettes/jobs/schedule/spider/extra.yml +38 -0
- data/spec/fixtures/vcr_cassettes/jobs/schedule/spider/minimal.yml +38 -0
- data/spec/fixtures/vcr_cassettes/jobs/schedule/spider/priority.yml +38 -0
- data/spec/fixtures/vcr_cassettes/jobs/stop/bad_auth.yml +38 -0
- data/spec/fixtures/vcr_cassettes/jobs/stop/job/already-stopped.yml +38 -0
- data/spec/fixtures/vcr_cassettes/jobs/stop/job/invalid.yml +38 -0
- data/spec/fixtures/vcr_cassettes/jobs/stop/job/valid.yml +38 -0
- data/spec/fixtures/vcr_cassettes/jobs/stop/project/invalid.yml +39 -0
- data/spec/fixtures/vcr_cassettes/jobs/update/bad_auth.yml +38 -0
- data/spec/fixtures/vcr_cassettes/jobs/update/has_tag.yml +38 -0
- data/spec/fixtures/vcr_cassettes/jobs/update/job.yml +38 -0
- data/spec/fixtures/vcr_cassettes/jobs/update/lacks_tag.yml +38 -0
- data/spec/fixtures/vcr_cassettes/jobs/update/no-query-filters.yml +38 -0
- data/spec/fixtures/vcr_cassettes/jobs/update/no-update-params.yml +38 -0
- data/spec/fixtures/vcr_cassettes/jobs/update/project/invalid.yml +39 -0
- data/spec/fixtures/vcr_cassettes/jobs/update/spider.yml +38 -0
- data/spec/fixtures/vcr_cassettes/jobs/update/state.yml +38 -0
- data/spec/integration/jobs_spec.rb +567 -0
- data/spec/spec_helper.rb +22 -0
- data/spec/unit/jobs_spec.rb +188 -0
- data/spec/unit/scrapinghub_spec.rb +8 -0
- metadata +200 -0
@@ -0,0 +1,567 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/../spec_helper"
|
2
|
+
|
3
|
+
shared_examples "connection_refused_returns_try" do
|
4
|
+
before do
|
5
|
+
stub_request(:any, "dash.scrapinghub.com").to_timeout
|
6
|
+
end
|
7
|
+
|
8
|
+
it "returns a Try::Failure when host is down" do
|
9
|
+
expect(jobs.send(action, args)).to be_a Kleisli::Try::Failure
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
shared_examples "bad_auth_returns_try" do |cassette|
|
14
|
+
use_vcr_cassette cassette
|
15
|
+
|
16
|
+
it "returns a Left when bad authentication is used" do
|
17
|
+
js = jobs.send(action, args)
|
18
|
+
expect(js).to be_a Kleisli::Either::Left
|
19
|
+
expect(js.left.class).to eq HTTParty::Response
|
20
|
+
expect(js.left.response).to be_a Net::HTTPForbidden
|
21
|
+
expect(js.left['status']).to eq("error")
|
22
|
+
expect(js.left["message"]).to match(/^Authentication failed$/)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "jobs integration" do
|
27
|
+
let(:api_key) { "XXX" }
|
28
|
+
let(:jobs) { Scrapinghub::Jobs.new(api_key: api_key) }
|
29
|
+
|
30
|
+
describe "list" do
|
31
|
+
let(:action) { :list }
|
32
|
+
let(:valid_project) { 1 }
|
33
|
+
let(:args) { {project: valid_project} }
|
34
|
+
|
35
|
+
it_behaves_like "connection_refused_returns_try"
|
36
|
+
it_behaves_like "bad_auth_returns_try", "jobs/list/bad_auth"
|
37
|
+
|
38
|
+
context "project" do
|
39
|
+
context "given a valid project ID" do
|
40
|
+
use_vcr_cassette "jobs/list/project/valid"
|
41
|
+
|
42
|
+
it "returns a Right" do
|
43
|
+
expect(jobs.send(action, args)).to be_a Kleisli::Either::Right
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context "given an invalid / non-owned project ID" do
|
48
|
+
use_vcr_cassette "jobs/list/project/invalid"
|
49
|
+
let(:invalid_project) { 2 }
|
50
|
+
let(:args) { {project: invalid_project} }
|
51
|
+
|
52
|
+
it "returns a Left" do
|
53
|
+
expect(jobs.send(action, args)).to be_a Kleisli::Either::Left
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context "job" do
|
59
|
+
context "given a single job" do
|
60
|
+
use_vcr_cassette "jobs/list/job/single"
|
61
|
+
let(:job) { "1/1/6" }
|
62
|
+
let(:args) { {project: valid_project, job: job} }
|
63
|
+
|
64
|
+
it "returns the job" do
|
65
|
+
js = jobs.send(action, args)
|
66
|
+
expect(js).to be_a Kleisli::Either::Right
|
67
|
+
expect(js.fmap{|j| j["total"]}.right).to eq(1)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context "given a list of multiple jobs" do
|
72
|
+
use_vcr_cassette "jobs/list/job/multiple"
|
73
|
+
let(:job) { ["1/1/1", "1/1/2"] }
|
74
|
+
let(:args) { {project: valid_project, job: job} }
|
75
|
+
|
76
|
+
it "returns the jobs" do
|
77
|
+
js = jobs.send(action, args)
|
78
|
+
expect(js).to be_a Kleisli::Either::Right
|
79
|
+
expect(js.fmap{|j| j["total"]}.right).to eq(2)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
context "given an invalid/non-existent job" do
|
84
|
+
use_vcr_cassette "jobs/list/job/invalid"
|
85
|
+
let(:job) { "1/1/123" }
|
86
|
+
let(:args) { {project: valid_project, job: job} }
|
87
|
+
|
88
|
+
it "returns no jobs" do
|
89
|
+
js = jobs.send(action, args)
|
90
|
+
expect(js).to be_a Kleisli::Either::Right
|
91
|
+
expect(js.fmap{|j| j["total"]}.right).to eq(0)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
context "spider" do
|
97
|
+
context "given a valid spider with ran jobs" do
|
98
|
+
use_vcr_cassette "jobs/list/spider/valid"
|
99
|
+
let(:spider) { "atlantic_firearms_crawl" }
|
100
|
+
let(:args) { {project: valid_project, spider: spider} }
|
101
|
+
|
102
|
+
it "returns a Right with the list of spider jobs" do
|
103
|
+
js = jobs.send(action, args)
|
104
|
+
expect(js).to be_a Kleisli::Either::Right
|
105
|
+
expect(js.fmap{|j| j["total"]}.right).to eq(5)
|
106
|
+
expect(js.fmap{|j| j["jobs"]}.fmap(&:size).right).to eq(5)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
context "given an invalid or not-ran spider" do
|
111
|
+
use_vcr_cassette "jobs/list/spider/invalid"
|
112
|
+
let(:spider) { "bar" }
|
113
|
+
let(:args) { {project: valid_project, spider: spider} }
|
114
|
+
|
115
|
+
it "returns a Right with no results" do
|
116
|
+
js = jobs.send(action, args)
|
117
|
+
expect(js).to be_a Kleisli::Either::Right
|
118
|
+
expect(js.fmap{|j| j["total"]}.right).to eq(0)
|
119
|
+
expect(js.fmap{|j| j["jobs"]}.fmap(&:size).right).to eq(0)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
context "state" do
|
125
|
+
context "given 'finished' with completed jobs" do
|
126
|
+
use_vcr_cassette "jobs/list/state/finished"
|
127
|
+
let(:state) { "finished" }
|
128
|
+
let(:args) { {project: valid_project, state: state} }
|
129
|
+
|
130
|
+
it "returns a Right with the list of spider jobs" do
|
131
|
+
js = jobs.send(action, args)
|
132
|
+
expect(js).to be_a Kleisli::Either::Right
|
133
|
+
expect(js.fmap{|j| j["total"]}.right).to eq(9)
|
134
|
+
expect(js.fmap{|j| j["jobs"]}.fmap(&:size).right).to eq(9)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
context "given 'pending' without pending jobs" do
|
139
|
+
use_vcr_cassette "jobs/list/state/pending"
|
140
|
+
let(:state) { "pending" }
|
141
|
+
let(:args) { {project: valid_project, state: state} }
|
142
|
+
|
143
|
+
it "returns a Right without any jobs" do
|
144
|
+
js = jobs.send(action, args)
|
145
|
+
expect(js).to be_a Kleisli::Either::Right
|
146
|
+
expect(js.fmap{|j| j["total"]}.right).to eq(0)
|
147
|
+
expect(js.fmap{|j| j["jobs"]}.fmap(&:size).right).to eq(0)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
context "has_tag" do
|
153
|
+
context "given a single tag" do
|
154
|
+
use_vcr_cassette "jobs/list/has_tag/single"
|
155
|
+
let(:has_tag) { "foo" }
|
156
|
+
let(:args) { {project: valid_project, has_tag: has_tag} }
|
157
|
+
|
158
|
+
it "returns jobs with that tag" do
|
159
|
+
js = jobs.send(action, args)
|
160
|
+
expect(js).to be_a Kleisli::Either::Right
|
161
|
+
expect(js.fmap{|j| j["total"]}.right).to eq(2)
|
162
|
+
js.fmap{|j| j["jobs"].map{|j| j["tags"]} }.right.each do |tags|
|
163
|
+
expect(tags).to include(has_tag)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
context "given a list of multiple tags" do
|
169
|
+
use_vcr_cassette "jobs/list/has_tag/multiple"
|
170
|
+
let(:has_tag) { ["foo", "bar"] }
|
171
|
+
let(:args) { {project: valid_project, has_tag: has_tag} }
|
172
|
+
|
173
|
+
it "returns all jobs with either tag" do
|
174
|
+
js = jobs.send(action, args)
|
175
|
+
expect(js).to be_a Kleisli::Either::Right
|
176
|
+
expect(js.fmap{|j| j["total"]}.right).to eq(3)
|
177
|
+
js.fmap{|j| j["jobs"].map{|j| j["tags"]} }.right.each do |tags|
|
178
|
+
in_common = tags & has_tag
|
179
|
+
expect(in_common).not_to be_empty
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
context "given an invalid/non-existent tag" do
|
185
|
+
use_vcr_cassette "jobs/list/has_tag/invalid"
|
186
|
+
let(:has_tag) { "baz" }
|
187
|
+
let(:args) { {project: valid_project, has_tag: has_tag} }
|
188
|
+
|
189
|
+
it "returns no jobs" do
|
190
|
+
js = jobs.send(action, args)
|
191
|
+
expect(js).to be_a Kleisli::Either::Right
|
192
|
+
expect(js.fmap{|j| j["total"]}.right).to eq(0)
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
context "lacks_tag" do
|
198
|
+
context "given a single tag" do
|
199
|
+
use_vcr_cassette "jobs/list/lacks_tag/single"
|
200
|
+
let(:lacks_tag) { "foo" }
|
201
|
+
let(:args) { {project: valid_project, lacks_tag: lacks_tag} }
|
202
|
+
|
203
|
+
it "returns jobs with that tag" do
|
204
|
+
js = jobs.send(action, args)
|
205
|
+
expect(js).to be_a Kleisli::Either::Right
|
206
|
+
expect(js.fmap{|j| j["total"]}.right).to eq(7)
|
207
|
+
js.fmap{|j| j["jobs"].map{|j| j["tags"]} }.right.each do |tags|
|
208
|
+
expect(tags).not_to include(lacks_tag)
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
context "given a list of tags" do
|
214
|
+
use_vcr_cassette "jobs/list/lacks_tag/multiple"
|
215
|
+
let(:lacks_tag) { ["foo", "bar"] }
|
216
|
+
let(:args) { {project: valid_project, lacks_tag: lacks_tag} }
|
217
|
+
|
218
|
+
it "returns all jobs without either tag" do
|
219
|
+
js = jobs.send(action, args)
|
220
|
+
expect(js).to be_a Kleisli::Either::Right
|
221
|
+
expect(js.fmap{|j| j["total"]}.right).to eq(6)
|
222
|
+
js.fmap{|j| j["jobs"].map{|j| j["tags"]} }.right.each do |tags|
|
223
|
+
in_common = tags & lacks_tag
|
224
|
+
expect(in_common).to be_empty
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
context "given an invalid/non-existent tag" do
|
230
|
+
use_vcr_cassette "jobs/list/lacks_tag/invalid"
|
231
|
+
let(:lacks_tag) { "baz" }
|
232
|
+
let(:args) { {project: valid_project, lacks_tag: lacks_tag} }
|
233
|
+
|
234
|
+
it "returns no jobs" do
|
235
|
+
js = jobs.send(action, args)
|
236
|
+
expect(js).to be_a Kleisli::Either::Right
|
237
|
+
expect(js.fmap{|j| j["total"]}.right).to eq(9)
|
238
|
+
js.fmap{|j| j["jobs"].map{|j| j["tags"]} }.right.each do |tags|
|
239
|
+
expect(tags).not_to include(lacks_tag)
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
context "count" do
|
246
|
+
context "given 3" do
|
247
|
+
use_vcr_cassette "jobs/list/count/3"
|
248
|
+
let(:count) { 3 }
|
249
|
+
let(:args) { {project: valid_project, count: count} }
|
250
|
+
|
251
|
+
it "returns 3 responses" do
|
252
|
+
js = jobs.send(action, args)
|
253
|
+
expect(js).to be_a Kleisli::Either::Right
|
254
|
+
expect(js.fmap{|j| j["total"]}.right).to eq(3)
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
describe "schedule" do
|
261
|
+
let(:action) { :schedule }
|
262
|
+
let(:valid_project) { 1 }
|
263
|
+
let(:args) { {project: valid_project, spider: "atlantic_firearms_crawl"} }
|
264
|
+
|
265
|
+
it_behaves_like "connection_refused_returns_try"
|
266
|
+
it_behaves_like "bad_auth_returns_try", "jobs/schedule/bad_auth"
|
267
|
+
|
268
|
+
context "project" do
|
269
|
+
context "given an invalid / non-owned project ID" do
|
270
|
+
use_vcr_cassette "jobs/schedule/project/invalid"
|
271
|
+
let(:invalid_project) { 2 }
|
272
|
+
|
273
|
+
it "returns a Left" do
|
274
|
+
js = jobs.send(action, args.merge(project: invalid_project))
|
275
|
+
expect(js).to be_a Kleisli::Either::Left
|
276
|
+
expect(js.left['status']).to eq("badrequest")
|
277
|
+
end
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
context "spider" do
|
282
|
+
context "given minimal parameters" do
|
283
|
+
use_vcr_cassette "jobs/schedule/spider/minimal"
|
284
|
+
|
285
|
+
it "returns ok status and the created jobid" do
|
286
|
+
js = jobs.send(action, args)
|
287
|
+
expect(js).to be_a Kleisli::Either::Right
|
288
|
+
expect(js.fmap{|j| j["status"]}.right).to eq("ok")
|
289
|
+
expect(js.fmap{|j| j["jobid"]}.right).to eq("1/1/11")
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
context "when an instance of the spider is already running" do
|
294
|
+
use_vcr_cassette "jobs/schedule/spider/already-running"
|
295
|
+
|
296
|
+
it "returns ok status and the error message" do
|
297
|
+
js = jobs.send(action, args)
|
298
|
+
expect(js).to be_a Kleisli::Either::Left
|
299
|
+
expect(js.left["status"]).to eq("error")
|
300
|
+
expect(js.left["message"]).to match(/^Spider.*already scheduled$/)
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
context "given an add_tag argument" do
|
305
|
+
use_vcr_cassette "jobs/schedule/spider/add_tag"
|
306
|
+
|
307
|
+
it "returns ok status and the created jobid" do
|
308
|
+
js = jobs.send(action, args.merge(add_tag: "foo"))
|
309
|
+
expect(js).to be_a Kleisli::Either::Right
|
310
|
+
expect(js.fmap{|j| j["status"]}.right).to eq("ok")
|
311
|
+
expect(js.fmap{|j| j["jobid"]}.right).to eq("1/1/14")
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
context "given a priority argument" do
|
316
|
+
use_vcr_cassette "jobs/schedule/spider/priority"
|
317
|
+
|
318
|
+
it "returns ok status and the created jobid" do
|
319
|
+
js = jobs.send(action, args.merge(priority: 4))
|
320
|
+
expect(js).to be_a Kleisli::Either::Right
|
321
|
+
expect(js.fmap{|j| j["status"]}.right).to eq("ok")
|
322
|
+
expect(js.fmap{|j| j["jobid"]}.right).to eq("1/1/16")
|
323
|
+
end
|
324
|
+
end
|
325
|
+
|
326
|
+
context "given an extra argument" do
|
327
|
+
use_vcr_cassette "jobs/schedule/spider/extra"
|
328
|
+
|
329
|
+
it "returns ok status and the created jobid" do
|
330
|
+
js = jobs.send(action, args.merge(extra: {:"DOWNLOAD_DELAY" => "0.5"}))
|
331
|
+
expect(js).to be_a Kleisli::Either::Right
|
332
|
+
expect(js.fmap{|j| j["status"]}.right).to eq("ok")
|
333
|
+
expect(js.fmap{|j| j["jobid"]}.right).to eq("1/1/17")
|
334
|
+
end
|
335
|
+
end
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
describe "delete" do
|
340
|
+
let(:action) { :delete }
|
341
|
+
let(:valid_project) { 1 }
|
342
|
+
let(:args) { {project: valid_project, job: "#{valid_project}/1/7"} }
|
343
|
+
|
344
|
+
it_behaves_like "connection_refused_returns_try"
|
345
|
+
it_behaves_like "bad_auth_returns_try", "jobs/delete/bad_auth"
|
346
|
+
|
347
|
+
context "project" do
|
348
|
+
context "given an invalid / non-owned project ID" do
|
349
|
+
use_vcr_cassette "jobs/delete/project/invalid"
|
350
|
+
let(:invalid_project) { 2 }
|
351
|
+
|
352
|
+
it "returns a Left" do
|
353
|
+
expect(jobs.send(action, args.merge(project: invalid_project))).to be_a Kleisli::Either::Left
|
354
|
+
end
|
355
|
+
end
|
356
|
+
end
|
357
|
+
|
358
|
+
context "job" do
|
359
|
+
context "given a single job" do
|
360
|
+
use_vcr_cassette "jobs/delete/job/single"
|
361
|
+
let(:job) { "#{valid_project}/3/4" }
|
362
|
+
let(:args) { {project: valid_project, job: job} }
|
363
|
+
|
364
|
+
it "returns the right count" do
|
365
|
+
js = jobs.send(action, args)
|
366
|
+
expect(js).to be_a Kleisli::Either::Right
|
367
|
+
expect(js.fmap{|j| j["count"]}.right).to eq(1)
|
368
|
+
end
|
369
|
+
end
|
370
|
+
|
371
|
+
context "given a list of multiple jobs" do
|
372
|
+
use_vcr_cassette "jobs/delete/job/multiple"
|
373
|
+
let(:job) { ["#{valid_project}/1/7", "#{valid_project}/1/8"] }
|
374
|
+
let(:args) { {project: valid_project, job: job} }
|
375
|
+
|
376
|
+
it "returns the right count" do
|
377
|
+
js = jobs.send(action, args)
|
378
|
+
expect(js).to be_a Kleisli::Either::Right
|
379
|
+
expect(js.fmap{|j| j["count"]}.right).to eq(2)
|
380
|
+
end
|
381
|
+
end
|
382
|
+
|
383
|
+
context "given an invalid/non-existent job" do
|
384
|
+
use_vcr_cassette "jobs/delete/job/invalid"
|
385
|
+
let(:job) { "#{valid_project}/1/123" }
|
386
|
+
let(:args) { {project: valid_project, job: job} }
|
387
|
+
|
388
|
+
it "returns count of 0" do
|
389
|
+
js = jobs.send(action, args)
|
390
|
+
expect(js).to be_a Kleisli::Either::Right
|
391
|
+
expect(js.fmap{|j| j["count"]}.right).to eq(0)
|
392
|
+
end
|
393
|
+
end
|
394
|
+
end
|
395
|
+
end
|
396
|
+
|
397
|
+
describe "stop" do
|
398
|
+
let(:action) { :stop }
|
399
|
+
let(:valid_project) { 1 }
|
400
|
+
let(:args) { {project: valid_project, job: "#{valid_project}/1/9"} }
|
401
|
+
|
402
|
+
it_behaves_like "connection_refused_returns_try"
|
403
|
+
it_behaves_like "bad_auth_returns_try", "jobs/stop/bad_auth"
|
404
|
+
|
405
|
+
context "project" do
|
406
|
+
context "given an invalid / non-owned project ID" do
|
407
|
+
use_vcr_cassette "jobs/stop/project/invalid"
|
408
|
+
let(:invalid_project) { 2 }
|
409
|
+
|
410
|
+
it "returns a Left" do
|
411
|
+
expect(jobs.send(action, args.merge(project: invalid_project))).to be_a Kleisli::Either::Left
|
412
|
+
end
|
413
|
+
end
|
414
|
+
end
|
415
|
+
|
416
|
+
context "job" do
|
417
|
+
context "given a valid job" do
|
418
|
+
use_vcr_cassette "jobs/stop/job/valid"
|
419
|
+
let(:job) { "#{valid_project}/1/9" }
|
420
|
+
let(:args) { {project: valid_project, job: job} }
|
421
|
+
|
422
|
+
it "returns ok" do
|
423
|
+
js = jobs.send(action, args)
|
424
|
+
expect(js).to be_a Kleisli::Either::Right
|
425
|
+
expect(js.fmap{|j| j["status"]}.right).to eq("ok")
|
426
|
+
end
|
427
|
+
end
|
428
|
+
|
429
|
+
context "given a non-existent job" do
|
430
|
+
use_vcr_cassette "jobs/stop/job/invalid"
|
431
|
+
let(:job) { "#{valid_project}/123/123" }
|
432
|
+
let(:args) { {project: valid_project, job: job} }
|
433
|
+
|
434
|
+
it "returns ok" do
|
435
|
+
js = jobs.send(action, args)
|
436
|
+
expect(js).to be_a Kleisli::Either::Right
|
437
|
+
expect(js.fmap{|j| j["status"]}.right).to eq("ok")
|
438
|
+
end
|
439
|
+
end
|
440
|
+
|
441
|
+
context "given an already-stopped job" do
|
442
|
+
use_vcr_cassette "jobs/stop/job/already-stopped"
|
443
|
+
let(:job) { "#{valid_project}/1/6" }
|
444
|
+
let(:args) { {project: valid_project, job: job} }
|
445
|
+
|
446
|
+
it "returns ok" do
|
447
|
+
js = jobs.send(action, args)
|
448
|
+
expect(js).to be_a Kleisli::Either::Right
|
449
|
+
expect(js.fmap{|j| j["status"]}.right).to eq("ok")
|
450
|
+
end
|
451
|
+
end
|
452
|
+
|
453
|
+
end
|
454
|
+
end
|
455
|
+
|
456
|
+
describe "update" do
|
457
|
+
let(:action) { :update }
|
458
|
+
let(:valid_project) { 1 }
|
459
|
+
let(:args) { {project: valid_project, job: "1/1/18"} }
|
460
|
+
|
461
|
+
it_behaves_like "connection_refused_returns_try"
|
462
|
+
it_behaves_like "bad_auth_returns_try", "jobs/update/bad_auth"
|
463
|
+
|
464
|
+
context "project" do
|
465
|
+
context "given an invalid / non-owned project ID" do
|
466
|
+
use_vcr_cassette "jobs/update/project/invalid"
|
467
|
+
let(:invalid_project) { 2 }
|
468
|
+
let(:args) { {project: invalid_project} }
|
469
|
+
|
470
|
+
it "returns an error" do
|
471
|
+
js = jobs.send(action, args)
|
472
|
+
expect(js).to be_a Kleisli::Either::Left
|
473
|
+
expect(js.left['status']).to eq("badrequest")
|
474
|
+
expect(js.left["message"]).to match(/^User.*doesn\'t have access to project/)
|
475
|
+
end
|
476
|
+
end
|
477
|
+
end
|
478
|
+
|
479
|
+
context "query filters" do
|
480
|
+
context "without query filters" do
|
481
|
+
use_vcr_cassette "jobs/update/no-query-filters"
|
482
|
+
let(:args) { {project: valid_project} }
|
483
|
+
|
484
|
+
it "returns an error" do
|
485
|
+
js = jobs.send(action, args)
|
486
|
+
expect(js).to be_a Kleisli::Either::Left
|
487
|
+
expect(js.left["status"]).to eq("badrequest")
|
488
|
+
expect(js.left["message"]).to match(/^No query filters provided$/)
|
489
|
+
end
|
490
|
+
end
|
491
|
+
|
492
|
+
context "filtering on job" do
|
493
|
+
use_vcr_cassette "jobs/update/job"
|
494
|
+
let(:args) { {project: valid_project, job: ["1/3/7", "1/1/18"], add_tag: "baz"} }
|
495
|
+
|
496
|
+
it "returns ok status and the affected count" do
|
497
|
+
js = jobs.send(action, args)
|
498
|
+
expect(js).to be_a Kleisli::Either::Right
|
499
|
+
expect(js.fmap{|j| j["status"]}.right).to eq("ok")
|
500
|
+
expect(js.fmap{|j| j["count"]}.right).to eq(2)
|
501
|
+
end
|
502
|
+
end
|
503
|
+
|
504
|
+
context "filtering on spider" do
|
505
|
+
use_vcr_cassette "jobs/update/spider"
|
506
|
+
let(:args) { {project: valid_project, spider: "atlantic_firearms_crawl", add_tag: "foo"} }
|
507
|
+
|
508
|
+
it "returns ok status and the affected count" do
|
509
|
+
js = jobs.send(action, args)
|
510
|
+
expect(js).to be_a Kleisli::Either::Right
|
511
|
+
expect(js.fmap{|j| j["status"]}.right).to eq("ok")
|
512
|
+
expect(js.fmap{|j| j["count"]}.right).to eq(11)
|
513
|
+
end
|
514
|
+
end
|
515
|
+
|
516
|
+
context "filtering on state" do
|
517
|
+
use_vcr_cassette "jobs/update/state"
|
518
|
+
let(:args) { {project: valid_project, state: "running", add_tag: "bar"} }
|
519
|
+
|
520
|
+
it "returns ok status and the affected count" do
|
521
|
+
js = jobs.send(action, args)
|
522
|
+
expect(js).to be_a Kleisli::Either::Right
|
523
|
+
expect(js.fmap{|j| j["status"]}.right).to eq("ok")
|
524
|
+
expect(js.fmap{|j| j["count"]}.right).to eq(2)
|
525
|
+
end
|
526
|
+
end
|
527
|
+
|
528
|
+
context "filtering on has_tag" do
|
529
|
+
use_vcr_cassette "jobs/update/has_tag"
|
530
|
+
let(:args) { {project: valid_project, has_tag: "bar", remove_tag: "bar"} }
|
531
|
+
|
532
|
+
it "returns ok status and the affected count" do
|
533
|
+
js = jobs.send(action, args)
|
534
|
+
expect(js).to be_a Kleisli::Either::Right
|
535
|
+
expect(js.fmap{|j| j["status"]}.right).to eq("ok")
|
536
|
+
expect(js.fmap{|j| j["count"]}.right).to eq(4)
|
537
|
+
end
|
538
|
+
end
|
539
|
+
|
540
|
+
context "filtering on lacks_tag" do
|
541
|
+
use_vcr_cassette "jobs/update/lacks_tag"
|
542
|
+
let(:args) { {project: valid_project, lacks_tag: "bar", add_tag: "bar"} }
|
543
|
+
|
544
|
+
it "returns ok status and the affected count" do
|
545
|
+
js = jobs.send(action, args)
|
546
|
+
expect(js).to be_a Kleisli::Either::Right
|
547
|
+
expect(js.fmap{|j| j["status"]}.right).to eq("ok")
|
548
|
+
expect(js.fmap{|j| j["count"]}.right).to eq(18)
|
549
|
+
end
|
550
|
+
end
|
551
|
+
end
|
552
|
+
|
553
|
+
context "update parameters" do
|
554
|
+
context "without update parameters" do
|
555
|
+
use_vcr_cassette "jobs/update/no-update-params"
|
556
|
+
|
557
|
+
it "returns an error" do
|
558
|
+
js = jobs.send(action, args)
|
559
|
+
expect(js).to be_a Kleisli::Either::Left
|
560
|
+
expect(js.left["status"]).to eq("badrequest")
|
561
|
+
expect(js.left["message"]).to match(/^No update modifiers provided$/)
|
562
|
+
end
|
563
|
+
end
|
564
|
+
end
|
565
|
+
end
|
566
|
+
|
567
|
+
end
|