neverbounce-api 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.codeclimate.yml +8 -0
- data/.gitignore +21 -0
- data/.rspec +4 -0
- data/.rubocop.yml +1161 -0
- data/.travis.yml +27 -0
- data/.yardopts +2 -0
- data/Gemfile +17 -0
- data/Gemfile.lock +48 -0
- data/LICENSE +9 -0
- data/README.md +235 -0
- data/lib/never_bounce/api/client.rb +259 -0
- data/lib/never_bounce/api/error.rb +21 -0
- data/lib/never_bounce/api/feature/basic_initialize.rb +20 -0
- data/lib/never_bounce/api/feature/eigencache.rb +48 -0
- data/lib/never_bounce/api/feature/igetset.rb +41 -0
- data/lib/never_bounce/api/feature/oattrs.rb +100 -0
- data/lib/never_bounce/api/feature/require_attr.rb +27 -0
- data/lib/never_bounce/api/request/account_info.rb +29 -0
- data/lib/never_bounce/api/request/base.rb +102 -0
- data/lib/never_bounce/api/request/jobs_create.rb +90 -0
- data/lib/never_bounce/api/request/jobs_delete.rb +34 -0
- data/lib/never_bounce/api/request/jobs_download.rb +34 -0
- data/lib/never_bounce/api/request/jobs_parse.rb +55 -0
- data/lib/never_bounce/api/request/jobs_results.rb +53 -0
- data/lib/never_bounce/api/request/jobs_search.rb +57 -0
- data/lib/never_bounce/api/request/jobs_start.rb +47 -0
- data/lib/never_bounce/api/request/jobs_status.rb +37 -0
- data/lib/never_bounce/api/request/single_check.rb +67 -0
- data/lib/never_bounce/api/response/account_info.rb +39 -0
- data/lib/never_bounce/api/response/account_info/job_counts.rb +26 -0
- data/lib/never_bounce/api/response/address_info.rb +43 -0
- data/lib/never_bounce/api/response/base.rb +15 -0
- data/lib/never_bounce/api/response/container.rb +126 -0
- data/lib/never_bounce/api/response/credits_info/base.rb +30 -0
- data/lib/never_bounce/api/response/credits_info/monthly.rb +16 -0
- data/lib/never_bounce/api/response/credits_info/paid.rb +20 -0
- data/lib/never_bounce/api/response/error_message.rb +17 -0
- data/lib/never_bounce/api/response/feature/job_status_fields.rb +68 -0
- data/lib/never_bounce/api/response/feature/job_status_fields/total.rb +46 -0
- data/lib/never_bounce/api/response/jobs_create.rb +10 -0
- data/lib/never_bounce/api/response/jobs_delete.rb +8 -0
- data/lib/never_bounce/api/response/jobs_download.rb +19 -0
- data/lib/never_bounce/api/response/jobs_parse.rb +10 -0
- data/lib/never_bounce/api/response/jobs_results.rb +34 -0
- data/lib/never_bounce/api/response/jobs_results/item.rb +65 -0
- data/lib/never_bounce/api/response/jobs_results/query.rb +20 -0
- data/lib/never_bounce/api/response/jobs_search.rb +33 -0
- data/lib/never_bounce/api/response/jobs_search/query.rb +16 -0
- data/lib/never_bounce/api/response/jobs_search/result.rb +13 -0
- data/lib/never_bounce/api/response/jobs_start.rb +10 -0
- data/lib/never_bounce/api/response/jobs_status.rb +11 -0
- data/lib/never_bounce/api/response/message.rb +32 -0
- data/lib/never_bounce/api/response/single_check.rb +68 -0
- data/lib/never_bounce/api/response/status_message.rb +17 -0
- data/lib/never_bounce/api/response/success_message.rb +12 -0
- data/lib/never_bounce/api/session.rb +141 -0
- data/lib/never_bounce/api/version.rb +4 -0
- data/lib/neverbounce-api.rb +4 -0
- data/lib/neverbounce.rb +3 -0
- data/neverbounce-api.gemspec +20 -0
- data/spec/lib/never_bounce/api/client_spec.rb +199 -0
- data/spec/lib/never_bounce/api/feature/basic_initialize_spec.rb +25 -0
- data/spec/lib/never_bounce/api/feature/eigencache_spec.rb +28 -0
- data/spec/lib/never_bounce/api/feature/igetset_spec.rb +45 -0
- data/spec/lib/never_bounce/api/feature/oattrs_spec.rb +72 -0
- data/spec/lib/never_bounce/api/feature/require_attr_spec.rb +25 -0
- data/spec/lib/never_bounce/api/request/account_info_spec.rb +29 -0
- data/spec/lib/never_bounce/api/request/base_spec.rb +6 -0
- data/spec/lib/never_bounce/api/request/jobs_create_spec.rb +89 -0
- data/spec/lib/never_bounce/api/request/jobs_delete_spec.rb +31 -0
- data/spec/lib/never_bounce/api/request/jobs_download_spec.rb +31 -0
- data/spec/lib/never_bounce/api/request/jobs_parse_spec.rb +44 -0
- data/spec/lib/never_bounce/api/request/jobs_results_spec.rb +42 -0
- data/spec/lib/never_bounce/api/request/jobs_search_spec.rb +40 -0
- data/spec/lib/never_bounce/api/request/jobs_start_spec.rb +44 -0
- data/spec/lib/never_bounce/api/request/jobs_status_spec.rb +31 -0
- data/spec/lib/never_bounce/api/request/single_check_spec.rb +44 -0
- data/spec/lib/never_bounce/api/response/account_info/job_counts_spec.rb +7 -0
- data/spec/lib/never_bounce/api/response/account_info_spec.rb +9 -0
- data/spec/lib/never_bounce/api/response/address_info_spec.rb +7 -0
- data/spec/lib/never_bounce/api/response/base_spec.rb +6 -0
- data/spec/lib/never_bounce/api/response/container_spec.rb +142 -0
- data/spec/lib/never_bounce/api/response/credits_info/base_spec.rb +31 -0
- data/spec/lib/never_bounce/api/response/credits_info/monthly_spec.rb +11 -0
- data/spec/lib/never_bounce/api/response/credits_info/paid_spec.rb +11 -0
- data/spec/lib/never_bounce/api/response/feature/job_status_fields/total_spec.rb +7 -0
- data/spec/lib/never_bounce/api/response/feature/job_status_fields_spec.rb +42 -0
- data/spec/lib/never_bounce/api/response/jobs_create_spec.rb +7 -0
- data/spec/lib/never_bounce/api/response/jobs_delete_spec.rb +7 -0
- data/spec/lib/never_bounce/api/response/jobs_download_spec.rb +7 -0
- data/spec/lib/never_bounce/api/response/jobs_parse_spec.rb +7 -0
- data/spec/lib/never_bounce/api/response/jobs_results/jobs_results_item_spec.rb +7 -0
- data/spec/lib/never_bounce/api/response/jobs_results/jobs_results_query_spec.rb +7 -0
- data/spec/lib/never_bounce/api/response/jobs_results_spec.rb +7 -0
- data/spec/lib/never_bounce/api/response/jobs_search/jobs_search_query_spec.rb +7 -0
- data/spec/lib/never_bounce/api/response/jobs_search/jobs_search_result_spec.rb +7 -0
- data/spec/lib/never_bounce/api/response/jobs_search_spec.rb +7 -0
- data/spec/lib/never_bounce/api/response/jobs_start_spec.rb +7 -0
- data/spec/lib/never_bounce/api/response/jobs_status_spec.rb +7 -0
- data/spec/lib/never_bounce/api/response/single_check_spec.rb +7 -0
- data/spec/lib/never_bounce/api/response/spec_helper.rb +8 -0
- data/spec/lib/never_bounce/api/session_spec.rb +140 -0
- data/spec/lib/never_bounce/api_spec.rb +8 -0
- data/spec/spec_helper.rb +49 -0
- data/spec/spec_support/include_dir_context.rb +22 -0
- data/spec/spec_support/simplecov.rb +18 -0
- metadata +210 -0
@@ -0,0 +1,142 @@
|
|
1
|
+
|
2
|
+
module NeverBounce; module API; module Response
|
3
|
+
describe Container do
|
4
|
+
include_dir_context __dir__
|
5
|
+
|
6
|
+
it_behaves_like "instantiatable"
|
7
|
+
it_behaves_like "properly inherited"
|
8
|
+
|
9
|
+
describe "#body_hash" do
|
10
|
+
it "requires `raw`" do
|
11
|
+
expect { newo.body_hash }.to raise_error(AttributeError, "Attribute must be set: raw")
|
12
|
+
end
|
13
|
+
|
14
|
+
it "generally works" do
|
15
|
+
r = newo(raw: '{"a":10}')
|
16
|
+
expect(r.body_hash).to eq({"a" => 10})
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe ".oattr" do
|
21
|
+
# NOTE: Tests for this section are a few "matrix" scenarios which reasonably cover possible combinations.
|
22
|
+
context "case 1" do
|
23
|
+
let(:klass) do
|
24
|
+
Class.new(described_class) do
|
25
|
+
oattr :a, :scalar
|
26
|
+
oattr :b, :scalar, type: :integer
|
27
|
+
oattr :c, :scalar, type: :integer, allow_nil: true
|
28
|
+
oattr :d, :writer
|
29
|
+
oattr :e, :custom
|
30
|
+
oattr :f, :scalar, type: :float
|
31
|
+
oattr :g, :scalar, type: :float, allow_nil: true
|
32
|
+
|
33
|
+
def d
|
34
|
+
@d ||= body_hash.fetch("d")
|
35
|
+
end
|
36
|
+
|
37
|
+
def e
|
38
|
+
@e ||= body_hash.fetch("e")
|
39
|
+
end
|
40
|
+
|
41
|
+
def e=(v)
|
42
|
+
@e = v
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
it "generally works" do
|
48
|
+
expect(klass.oattrs).to eq [:a, :b, :c, :d, :e, :f, :g]
|
49
|
+
|
50
|
+
r = klass.new(body_hash: {})
|
51
|
+
expect { r.a }.to raise_error KeyError
|
52
|
+
expect { r.d }.to raise_error KeyError
|
53
|
+
expect { r.e }.to raise_error KeyError
|
54
|
+
expect { r.f }.to raise_error KeyError
|
55
|
+
|
56
|
+
# Numeric conversion, valid values.
|
57
|
+
r = klass.new(body_hash: {
|
58
|
+
"b" => "12",
|
59
|
+
"c" => "34",
|
60
|
+
"f" => "1.2",
|
61
|
+
"g" => "3.4",
|
62
|
+
})
|
63
|
+
expect(r.b).to eq 12
|
64
|
+
expect(r.c).to eq 34
|
65
|
+
expect(r.f).to eq 1.2
|
66
|
+
expect(r.g).to eq 3.4
|
67
|
+
|
68
|
+
# Numeric conversion, empty strings.
|
69
|
+
r = klass.new(body_hash: {
|
70
|
+
"b" => "",
|
71
|
+
"c" => "",
|
72
|
+
"f" => "",
|
73
|
+
"g" => "",
|
74
|
+
})
|
75
|
+
expect { r.b }.to raise_error(ArgumentError, /^invalid value for Integer/)
|
76
|
+
expect { r.c }.to raise_error(ArgumentError, /^invalid value for Integer/)
|
77
|
+
expect { r.f }.to raise_error(ArgumentError, /^invalid value for Float/)
|
78
|
+
expect { r.g }.to raise_error(ArgumentError, /^invalid value for Float/)
|
79
|
+
|
80
|
+
# Numeric conversion, invalid strings.
|
81
|
+
r = klass.new(body_hash: {
|
82
|
+
"b" => "xyz",
|
83
|
+
"c" => "xyz",
|
84
|
+
"f" => "xyz",
|
85
|
+
"g" => "xyz",
|
86
|
+
})
|
87
|
+
expect { r.b }.to raise_error(ArgumentError, /^invalid value for Integer/)
|
88
|
+
expect { r.c }.to raise_error(ArgumentError, /^invalid value for Integer/)
|
89
|
+
expect { r.f }.to raise_error(ArgumentError, /^invalid value for Float/)
|
90
|
+
expect { r.g }.to raise_error(ArgumentError, /^invalid value for Float/)
|
91
|
+
|
92
|
+
# Nill allowance.
|
93
|
+
r = klass.new(body_hash: {
|
94
|
+
"b" => nil,
|
95
|
+
"c" => nil,
|
96
|
+
"f" => nil,
|
97
|
+
"g" => nil,
|
98
|
+
})
|
99
|
+
expect { r.b }.to raise_error(TypeError, /nil into Integer/)
|
100
|
+
expect(r.c).to be nil
|
101
|
+
expect { r.f }.to raise_error(TypeError, /nil into Float/)
|
102
|
+
expect(r.g).to be nil
|
103
|
+
|
104
|
+
# Complete set.
|
105
|
+
r = klass.new(body_hash: {
|
106
|
+
"a" => "hello",
|
107
|
+
"b" => 10,
|
108
|
+
"c" => 20,
|
109
|
+
"d" => [1, 2, 3],
|
110
|
+
"e" => {kk: 1},
|
111
|
+
"f" => 1.5,
|
112
|
+
"g" => 2.6,
|
113
|
+
})
|
114
|
+
|
115
|
+
expect { r.touch }.not_to raise_error # An important one.
|
116
|
+
|
117
|
+
expect(r.a).to eq "hello"
|
118
|
+
expect(r.b).to eq 10
|
119
|
+
expect(r.c).to eq 20
|
120
|
+
expect(r.d).to eq([1, 2, 3])
|
121
|
+
expect(r.e).to eq({kk: 1})
|
122
|
+
expect(r.f).to eq 1.5
|
123
|
+
expect(r.g).to eq 2.6
|
124
|
+
|
125
|
+
# Accessors.
|
126
|
+
r.a += "!"
|
127
|
+
expect(r.a).to eq "hello!"
|
128
|
+
r.b += 1
|
129
|
+
expect(r.b).to eq 11
|
130
|
+
r.c += 1
|
131
|
+
expect(r.c).to eq 21
|
132
|
+
r.d += [4]
|
133
|
+
expect(r.d).to eq [1, 2, 3, 4]
|
134
|
+
r.f += 0.1
|
135
|
+
expect(r.f).to eq 1.6
|
136
|
+
r.g += 0.1
|
137
|
+
expect(r.g).to eq 2.7
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end; end; end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
|
2
|
+
describe NeverBounce::API::Response::CreditsInfo::Base do
|
3
|
+
include_dir_context __dir__
|
4
|
+
|
5
|
+
it_behaves_like "instantiatable"
|
6
|
+
it_behaves_like "properly inherited"
|
7
|
+
|
8
|
+
let(:klass) do
|
9
|
+
Class.new(described_class) do
|
10
|
+
attr_accessor :subscription_type
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "#monthly?" do
|
15
|
+
it "generally works" do
|
16
|
+
r = klass.new
|
17
|
+
r.subscription_type = :monthly
|
18
|
+
expect(r.monthly?).to be true
|
19
|
+
expect(r.paid?).to be false
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "#paid?" do
|
24
|
+
it "generally works" do
|
25
|
+
r = klass.new
|
26
|
+
r.subscription_type = :paid
|
27
|
+
expect(r.monthly?).to be false
|
28
|
+
expect(r.paid?).to be true
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
|
2
|
+
describe NeverBounce::API::Response::CreditsInfo::Monthly do
|
3
|
+
include_dir_context __dir__
|
4
|
+
|
5
|
+
it_behaves_like "instantiatable"
|
6
|
+
it_behaves_like "properly inherited"
|
7
|
+
|
8
|
+
describe "#subscription_type" do
|
9
|
+
it { expect(newo.subscription_type).to eq :monthly }
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
|
2
|
+
describe NeverBounce::API::Response::CreditsInfo::Paid do
|
3
|
+
include_dir_context __dir__
|
4
|
+
|
5
|
+
it_behaves_like "instantiatable"
|
6
|
+
it_behaves_like "properly inherited"
|
7
|
+
|
8
|
+
describe "#subscription_type" do
|
9
|
+
it { expect(newo.subscription_type).to eq :paid }
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
|
2
|
+
module NeverBounce; module API; module Response; module Feature
|
3
|
+
describe JobStatusFields do
|
4
|
+
context "when invalid class" do
|
5
|
+
it "generally works" do
|
6
|
+
feature = described_class
|
7
|
+
expect { Class.new { feature.load(self) } }.to raise_error(ArgumentError, /is not an ancestor of Response::Container$/)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
context "when valid class" do
|
12
|
+
it "generally works" do
|
13
|
+
feature = described_class
|
14
|
+
|
15
|
+
klass = Class.new(Response::StatusMessage) { feature.load(self) }
|
16
|
+
|
17
|
+
# Use a complete real-world example.
|
18
|
+
r = klass.new(body_hash: {"status"=>"success", "id"=>302499, "job_status"=>"complete", "filename"=>"20170815-103321.csv", "created_at"=>"2017-08-15 17:19:41", "started_at"=>"2017-08-15 17:19:42", "finished_at"=>"2017-08-15 17:19:45", "total"=>{"records"=>11, "billable"=>12, "processed"=>13, "valid"=>14, "invalid"=>15, "catchall"=>16, "disposable"=>17, "unknown"=>18, "duplicates"=>19, "bad_syntax"=>20}, "bounce_estimate"=>34.56, "percent_complete"=>100, "execution_time"=>99})
|
19
|
+
expect(r.id).to eq 302499
|
20
|
+
expect(r.job_status).to eq "complete"
|
21
|
+
expect(r.filename).to eq "20170815-103321.csv"
|
22
|
+
expect(r.created_at).to eq "2017-08-15 17:19:41"
|
23
|
+
expect(r.started_at).to eq "2017-08-15 17:19:42"
|
24
|
+
expect(r.finished_at).to eq "2017-08-15 17:19:45"
|
25
|
+
expect(r.bounce_estimate).to eq 34.56
|
26
|
+
expect(r.percent_complete).to eq 100
|
27
|
+
expect(r.execution_time).to eq 99
|
28
|
+
expect(total = r.total).to be_a described_class::Total
|
29
|
+
expect(total.records).to eq 11
|
30
|
+
expect(total.billable).to eq 12
|
31
|
+
expect(total.processed).to eq 13
|
32
|
+
expect(total.valid).to eq 14
|
33
|
+
expect(total.invalid).to eq 15
|
34
|
+
expect(total.catchall).to eq 16
|
35
|
+
expect(total.disposable).to eq 17
|
36
|
+
expect(total.unknown).to eq 18
|
37
|
+
expect(total.duplicates).to eq 19
|
38
|
+
expect(total.bad_syntax).to eq 20
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end; end; end; end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
|
2
|
+
module NeverBounce; module API
|
3
|
+
describe Session do
|
4
|
+
include_dir_context __dir__
|
5
|
+
|
6
|
+
it_behaves_like "instantiatable"
|
7
|
+
|
8
|
+
describe "#server_raw" do
|
9
|
+
let(:m) { :server_raw }
|
10
|
+
context "when NOK" do
|
11
|
+
it "generally works" do
|
12
|
+
r = newo(
|
13
|
+
server_obj: Class.new do
|
14
|
+
def code; 123; end
|
15
|
+
def ok?; false; end
|
16
|
+
end.new
|
17
|
+
)
|
18
|
+
expect { r.send(m) }.to raise_error(RequestError, "Code not OK: 123")
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context "when OK" do
|
23
|
+
it "generally works" do
|
24
|
+
r = newo(
|
25
|
+
server_obj: Class.new do
|
26
|
+
def body; "abc"; end
|
27
|
+
def ok?; true; end
|
28
|
+
end.new,
|
29
|
+
)
|
30
|
+
expect(r.send(m)).to eq "abc"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end # describe "#server_raw"
|
34
|
+
|
35
|
+
describe "#robj_hash_preview" do
|
36
|
+
let(:m) { :robj_hash_preview }
|
37
|
+
|
38
|
+
context "when unknown content type" do
|
39
|
+
it "generally works" do
|
40
|
+
r = newo(server_content_type: "type/a")
|
41
|
+
expect(r.send(m)).to be false
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context "when 'application/json'" do
|
46
|
+
it "generally works" do
|
47
|
+
r = newo(
|
48
|
+
server_content_type: "application/json",
|
49
|
+
server_raw: "xyz",
|
50
|
+
)
|
51
|
+
expect { r.send(m) }.to raise_error(FormatError, /^JSON::ParserError: /)
|
52
|
+
|
53
|
+
r = newo(
|
54
|
+
server_content_type: "application/json",
|
55
|
+
server_raw: '{"a":12,"b":"abc"}',
|
56
|
+
)
|
57
|
+
expect(r.send(m)).to eq({"a" => 12, "b" => "abc"})
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "#robj_klass_and_attrs" do
|
63
|
+
let(:m) { :robj_klass_and_attrs }
|
64
|
+
|
65
|
+
# A minimum viable instance for tests below.
|
66
|
+
def newo(attrs = {})
|
67
|
+
request_klass = Class.new do
|
68
|
+
def self.response_klass; Response::JobsParse; end
|
69
|
+
end
|
70
|
+
|
71
|
+
Class.new(described_class) do
|
72
|
+
def server_obj; raise "This must never be called"; end
|
73
|
+
end.new({
|
74
|
+
request: request_klass.new,
|
75
|
+
server_raw: "server_raw",
|
76
|
+
}.merge(attrs))
|
77
|
+
end
|
78
|
+
|
79
|
+
it "validates `robj_hash_preview`" do
|
80
|
+
r = newo(robj_hash_preview: "abc")
|
81
|
+
expect { r.send(m) }.to raise_error(AttributeError, "Unknown `robj_hash_preview`: \"abc\"")
|
82
|
+
end
|
83
|
+
|
84
|
+
it "works for raw data" do
|
85
|
+
r = newo(
|
86
|
+
robj_hash_preview: false,
|
87
|
+
)
|
88
|
+
#expect { r.send(m) }.to raise_error(FormatError, /^Key 'status' not found: /)
|
89
|
+
expect(r.send(m)).to eq [Response::JobsParse, {:raw => "server_raw"}]
|
90
|
+
end
|
91
|
+
|
92
|
+
it "works for invalid data" do
|
93
|
+
# Valid JSON.
|
94
|
+
r = newo(
|
95
|
+
robj_hash_preview: {"a" => 12},
|
96
|
+
)
|
97
|
+
expect { r.send(m) }.to raise_error(FormatError, /^Key 'status' not found: /)
|
98
|
+
end
|
99
|
+
|
100
|
+
it "works for valid data" do
|
101
|
+
r = newo(
|
102
|
+
robj_hash_preview: {"status" => "success"},
|
103
|
+
)
|
104
|
+
expect(r.send(m)).to eq [Response::JobsParse, {:body_hash=>{"status"=>"success"}}]
|
105
|
+
|
106
|
+
r = newo(
|
107
|
+
robj_hash_preview: {"status" => "not-a-success"}, # Not necessarily "error".
|
108
|
+
)
|
109
|
+
expect(r.send(m)).to eq [Response::ErrorMessage, {:body_hash=>{"status"=>"not-a-success"}}]
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
describe "#server_obj" do
|
114
|
+
it "requires `request`" do
|
115
|
+
r = newo
|
116
|
+
expect { r.server_obj }.to raise_error "Attribute must be set: request"
|
117
|
+
end
|
118
|
+
|
119
|
+
it "generally works" do
|
120
|
+
# See implementation notes below.
|
121
|
+
r = newo(
|
122
|
+
httparty: (httparty = cllggr.new),
|
123
|
+
request: Request::JobsParse.new(api_key: "api_key", job_id: "123"),
|
124
|
+
)
|
125
|
+
expect(r.server_obj).to eq 1 # Result of `cllggr`.
|
126
|
+
args = httparty._calls[0]
|
127
|
+
expect(args).to be_a Array
|
128
|
+
expect(args).not_to be_empty
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end; end
|
133
|
+
|
134
|
+
# Implementation notes:
|
135
|
+
#
|
136
|
+
# * We test class's general abilities on a real request class.
|
137
|
+
# * Consider this great hack to debug tests easier:
|
138
|
+
# Class.new(described_class) do
|
139
|
+
# def server_obj; raise "This must never be called"; end
|
140
|
+
# end.new(...)
|