gecko 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.
@@ -0,0 +1,36 @@
1
+ require 'helper'
2
+
3
+ describe Gecko::Widget::Pie do
4
+ it_behaves_like "a Gecko::Widget"
5
+
6
+ describe '#payload' do
7
+ before(:each) do
8
+ @widget = described_class.new('widget_key')
9
+ end
10
+
11
+ it 'should be empty by default' do
12
+ expect(@widget.payload).to be_a_valid_payload(
13
+ TEST_API_KEY,
14
+ {
15
+ :item => []
16
+ }
17
+ )
18
+ end
19
+
20
+ it 'should be correct hash when values assigned' do
21
+ @widget.add(1, 'first', '#cc0000')
22
+ @widget.add(2, 'second', '#ffffff')
23
+ @widget.add(3, 'third')
24
+ expect(@widget.payload).to be_a_valid_payload(
25
+ TEST_API_KEY,
26
+ {
27
+ :item => [
28
+ {:value => 1, :label => 'first', :colour => '#cc0000'},
29
+ {:value => 2, :label => 'second', :colour => '#ffffff'},
30
+ {:value => 3, :label => 'third'},
31
+ ]
32
+ }
33
+ )
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,48 @@
1
+ require 'helper'
2
+
3
+ shared_examples "a RAG" do
4
+ it_behaves_like "a Gecko::Widget"
5
+
6
+ describe '#payload' do
7
+ before(:each) do
8
+ @widget = described_class.new('widget_key')
9
+ end
10
+
11
+ it 'should be empty by default' do
12
+ expect(@widget.payload).to be_a_valid_payload(
13
+ TEST_API_KEY,
14
+ {:item => [
15
+ {:value => nil, :text => nil},
16
+ {:value => nil, :text => nil},
17
+ {:value => nil, :text => nil}
18
+ ]}
19
+ )
20
+ end
21
+
22
+ it 'should be correct hash when values assigned' do
23
+ @widget.green_text = 'green text'
24
+ @widget.green_value = 1
25
+ @widget.amber_text = 'amber text'
26
+ @widget.amber_value = 2
27
+ @widget.red_text = 'red text'
28
+ @widget.red_value = 3
29
+
30
+ expect(@widget.payload).to be_a_valid_payload(
31
+ TEST_API_KEY,
32
+ {:item => [
33
+ {:value => 3, :text => 'red text'},
34
+ {:value => 2, :text => 'amber text'},
35
+ {:value => 1, :text => 'green text'},
36
+ ]}
37
+ )
38
+ end
39
+ end
40
+ end
41
+
42
+ describe Gecko::Widget::Rag do
43
+ it_behaves_like "a RAG"
44
+ end
45
+
46
+ describe Gecko::Widget::RagColumns do
47
+ it_behaves_like "a RAG"
48
+ end
@@ -0,0 +1,49 @@
1
+ require 'helper'
2
+
3
+ describe Gecko::Widget::Text do
4
+ it_behaves_like "a Gecko::Widget"
5
+
6
+ describe described_class::Item do
7
+ describe '#initialize' do
8
+ it 'should raise error if undefined type given' do
9
+ expect{ described_class::Item.new('text', :undefined_type) }.to raise_error(ArgumentError)
10
+ end
11
+ end
12
+ end
13
+
14
+ describe '#reset' do
15
+ before(:each) do
16
+ @widget = described_class.new('widget_key')
17
+ @widget.add('this is test')
18
+ end
19
+ it 'should clear items' do
20
+ @widget.reset
21
+ expect(@widget.count).to be(0)
22
+ end
23
+ end
24
+
25
+ describe '#payload' do
26
+ before(:each) do
27
+ @widget = described_class.new('widget_key')
28
+ end
29
+
30
+ it 'should be empty by default' do
31
+ expect(@widget.payload).to be_a_valid_payload(
32
+ TEST_API_KEY,
33
+ {:item => []}
34
+ )
35
+ end
36
+
37
+ it 'should be correct hash when values assigned' do
38
+ @widget.add('this is the text')
39
+ @widget.add('more text', :alert)
40
+ expect(@widget.payload).to be_a_valid_payload(
41
+ TEST_API_KEY,
42
+ {:item => [
43
+ {:text => 'this is the text', :type => described_class::Item::TYPES[:normal]},
44
+ {:text => 'more text', :type => described_class::Item::TYPES[:alert]}
45
+ ]}
46
+ )
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,31 @@
1
+ require 'helper'
2
+
3
+ describe Gecko do
4
+ describe '#config' do
5
+ it 'should return a config object' do
6
+ expect(described_class.config).to be_a described_class::Configurator
7
+ end
8
+
9
+ it 'should yield config object' do
10
+ expect{ |p| described_class.config(&p) }.to yield_with_args(described_class::Configurator)
11
+ end
12
+
13
+ it 'should allow setting/getting #api_key' do
14
+ api_key = 'abc1234'
15
+ described_class.config.api_key = api_key
16
+ described_class.config.api_key.should eql api_key
17
+ end
18
+
19
+ it '#http_builder by default should not respond to call' do
20
+ described_class.config.http_builder # nil out any previous values
21
+ expect(described_class.config.connection_builder.respond_to?(:call)).to be_false
22
+ end
23
+
24
+ it '#http_builder should allow setting via block' do
25
+ proc = Proc.new { 1 }
26
+ described_class.config.http_builder(&proc)
27
+ expect(described_class.config.connection_builder.respond_to?(:call)).to be_true
28
+ expect(described_class.config.connection_builder).to be proc
29
+ end
30
+ end
31
+ end
data/spec/helper.rb ADDED
@@ -0,0 +1,25 @@
1
+ require 'gecko'
2
+ require 'rspec'
3
+
4
+ Dir["./spec/support/**/*.rb"].sort.each { |f| require f }
5
+
6
+ Faraday.default_adapter = :test
7
+
8
+ RSpec::Matchers.define :be_a_valid_payload do |api_key, data|
9
+ def payload(api_key, data)
10
+ {:api_key => api_key, :data => data}
11
+ end
12
+ match do |actual|
13
+ actual.kind_of?(Hash) && actual == payload(api_key, data)
14
+ end
15
+ failure_message_for_should do |actual|
16
+ "expected that\n#{actual.inspect}\nwould be\n#{payload(api_key, data).inspect}"
17
+ end
18
+ end
19
+
20
+ # Thanks https://gist.github.com/1428875
21
+ class MockBlock
22
+ def to_proc
23
+ lambda { |*a| call(*a) }
24
+ end
25
+ end
data/spec/http_spec.rb ADDED
@@ -0,0 +1,141 @@
1
+ require 'helper'
2
+
3
+ describe Gecko::Http do
4
+ def stub_post(url, request_body = {}, &response)
5
+ stub = Faraday::Adapter::Test::Stubs.new do |stub|
6
+ stub.post(url, MultiJson.encode(request_body), &response)
7
+ end
8
+ described_class.new do |builder|
9
+ builder.adapter :test, stub
10
+ end
11
+ end
12
+
13
+ describe '#initialize' do
14
+ after(:all) do
15
+ # reset config
16
+ Gecko.config.http_builder { }
17
+ end
18
+
19
+ it 'should yield connection builder' do
20
+ expect{ |p| described_class.new(&p) }.to yield_with_args(Faraday::Connection)
21
+ end
22
+
23
+ it 'should use Gecko.config.connection_builder' do
24
+ Gecko.config.http_builder { |c|
25
+ expect(c).to be_a(Faraday::Connection)
26
+ }
27
+ Gecko.config.connection_builder.should_receive(:call).and_call_original
28
+ described_class.new
29
+ end
30
+ end
31
+
32
+ describe '#post' do
33
+ it 'fails if non-json result given' do
34
+ http = stub_post('/test', {:test => true}) { [200, {}, 'caca'] }
35
+ expect { http.post('/test', {:test => true}) }.to raise_exception(MultiJson::DecodeError)
36
+ end
37
+
38
+ it 'should return a Result object' do
39
+ http = stub_post('/test', {:test => true}) { [200, {}, MultiJson.encode({})] }
40
+ expect(http.post('/test', {:test => true})).to be_a(described_class::Result)
41
+ end
42
+
43
+ it 'should yield a Faraday::Request instance' do
44
+ http = stub_post('/test', {:test => true}) { [200, {}, MultiJson.encode({})] }
45
+ expect { |p| http.post('/test', {:test => true}, &p) }.to yield_with_args(Faraday::Request)
46
+ end
47
+
48
+ describe described_class::Result do
49
+ context 'success response' do
50
+ before(:each) do
51
+ @http = stub_post('/test', {:test => true}) { [200, {}, MultiJson.encode({:success => true, :other_key => {:nested_key => 1234}})] }
52
+ @response = @http.post('/test', {:test => true})
53
+ end
54
+
55
+ it '#response_body should be a converted from JSON' do
56
+ expect(@response.response_body).to eq({:success => true, :other_key => {:nested_key => 1234}})
57
+ end
58
+
59
+ it '#http_200? should be true' do
60
+ expect(@response.http_200?).to be_true
61
+ end
62
+
63
+ it '#error? should be false' do
64
+ expect(@response.error?).to be_false
65
+ end
66
+
67
+ it '#success? should be true' do
68
+ expect(@response.success?).to be_true
69
+ end
70
+
71
+ it '#fetch should work with nested keys' do
72
+ expect(@response.fetch(:other_key, :nested_key)).to eq(1234)
73
+ end
74
+
75
+ it '#fetch should return nil if key does not exist' do
76
+ expect(@response.fetch(:weird_key, :nested_key)).to be_nil
77
+ end
78
+
79
+ it '#error should return an Error instance' do
80
+ expect(@response.error).to be_a(described_class::Result::Error)
81
+ end
82
+
83
+ it '#error should be empty' do
84
+ error = @response.error
85
+ expect(error.text).to be_nil
86
+ expect(error.status).to eq(200)
87
+ end
88
+
89
+ it '#on_complete should call block with correct params' do
90
+ expect{ |p| @response.on_complete(&p) }.to yield_with_args(true, described_class::Result)
91
+ end
92
+ end
93
+
94
+ context 'error response' do
95
+ before(:each) do
96
+ @http = stub_post('/test', {:test => true}) { [400, {}, MultiJson.encode({:success => false, :error => {:nested_key => 1234}})] }
97
+ @response = @http.post('/test', {:test => true})
98
+ end
99
+
100
+ it '#response_body should be a converted from JSON' do
101
+ expect(@response.response_body).to eq({:success => false, :error => {:nested_key => 1234}})
102
+ end
103
+
104
+ it '#http_200? should be true' do
105
+ expect(@response.http_200?).to be_false
106
+ end
107
+
108
+ it '#error? should be false' do
109
+ expect(@response.error?).to be_true
110
+ end
111
+
112
+ it '#success? should be true' do
113
+ expect(@response.success?).to be_false
114
+ end
115
+
116
+ it '#fetch should work with nested keys' do
117
+ expect(@response.fetch(:error, :nested_key)).to eq(1234)
118
+ end
119
+
120
+ it '#fetch should return nil if key does not exist' do
121
+ expect(@response.fetch(:weird_key, :nested_key)).to be_nil
122
+ end
123
+
124
+ it '#error should return an Error instance' do
125
+ expect(@response.error).to be_a(described_class::Result::Error)
126
+ end
127
+
128
+ it '#error should be populated' do
129
+ error = @response.error
130
+ expect(error.text).to eq({:nested_key => 1234})
131
+ expect(error.status).to eq(400)
132
+ end
133
+
134
+ it '#on_complete should call block with correct params' do
135
+ expect { |p| @response.on_complete(&p) }.to yield_with_args(false, described_class::Result)
136
+ end
137
+ end
138
+ end
139
+ end
140
+
141
+ end
@@ -0,0 +1,64 @@
1
+ require 'helper'
2
+
3
+ TEST_API_KEY = 'gecko.rb-api_key'
4
+ shared_examples 'a Gecko::Widget' do
5
+ before(:all) do
6
+ Gecko.config do |c|
7
+ c.api_key = TEST_API_KEY
8
+ end
9
+ end
10
+
11
+ describe '#initialize' do
12
+ it 'should receive a list of keys' do
13
+ widget = described_class.new('widget_key_A', 'widget_key_B')
14
+ expect(widget.keys).to eq(['widget_key_A', 'widget_key_B'])
15
+ end
16
+
17
+ it 'should receive an array' do
18
+ widget = described_class.new(['widget_key_A', 'widget_key_B'])
19
+ expect(widget.keys).to eq(['widget_key_A', 'widget_key_B'])
20
+ end
21
+
22
+ it 'should yield itself to a block' do
23
+ expect { |p| described_class.new('widget_key', &p) }.to yield_with_args(described_class)
24
+ end
25
+
26
+ it 'should raise error if no keys given' do
27
+ expect { described_class.new }.to raise_error(ArgumentError)
28
+ end
29
+ end
30
+
31
+ describe '#keys=' do
32
+ before(:each) do
33
+ @widget = described_class.new('key')
34
+ end
35
+ it 'should receive a key' do
36
+ @widget.keys = 'widget_key_A'
37
+ expect(@widget.keys).to eq(['widget_key_A'])
38
+ end
39
+
40
+ it 'should receive a list of keys' do
41
+ @widget.keys = 'widget_key_A', 'widget_key_B'
42
+ expect(@widget.keys).to eq(['widget_key_A', 'widget_key_B'])
43
+ end
44
+
45
+ it 'should receive an array of keys' do
46
+ @widget.keys = ['widget_key_A', 'widget_key_B']
47
+ expect(@widget.keys).to eq(['widget_key_A', 'widget_key_B'])
48
+ end
49
+ end
50
+
51
+ describe '#keys' do
52
+ it 'should be an array' do
53
+ widget = described_class.new('widget_key_1234')
54
+ expect(widget.keys).to be_kind_of(Array)
55
+ end
56
+ end
57
+
58
+ describe '#config' do
59
+ it 'should yield self' do
60
+ widget = described_class.new('widget_key_1234')
61
+ expect { |p| widget.config(&p) }.to yield_with_args(widget)
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,172 @@
1
+ require 'helper'
2
+
3
+ describe Gecko::Widget do
4
+ before(:all) do
5
+ Gecko.config do |c|
6
+ c.api_push_url = '/v1/send/:widget_key'
7
+ c.api_key = TEST_API_KEY
8
+ end
9
+ end
10
+
11
+ def create_widget(*keys, &response)
12
+ @widget = described_class.new(*keys)
13
+ stubs = Faraday::Adapter::Test::Stubs.new do |stub|
14
+ @widget.keys.each do |key|
15
+ stub.post(@widget.push_url(key), MultiJson.encode(@widget.payload), &response)
16
+ end
17
+ end
18
+ Gecko.config.http_builder do |builder|
19
+ builder.adapter :test, stubs
20
+ end
21
+ end
22
+
23
+ context 'Widget with 1 key, successful response' do
24
+ before(:each) do
25
+ create_widget('widget_key1') do
26
+ [200, {}, MultiJson.encode({:success => true})]
27
+ end
28
+ end
29
+
30
+ describe '#update' do
31
+ it 'should return 1 request objects' do
32
+ update_result = @widget.update
33
+ expect(update_result).to be_a(Array)
34
+ expect(update_result).to have(1).items
35
+ update_result.each do |result|
36
+ expect(result).to be_a(Gecko::Http::Result)
37
+ end
38
+ end
39
+
40
+ it 'should evoke callback passed to #update' do
41
+ callback = MockBlock.new
42
+ callback.should_receive(:call).once.with do |success, result, key|
43
+ expect(success).to be_true
44
+ expect(result).to be_a(Gecko::Http::Result)
45
+ expect(key).to eq('widget_key1')
46
+ end
47
+ @widget.update(&callback)
48
+ end
49
+
50
+ it 'should evoke callback passed to #on_update' do
51
+ callback = MockBlock.new
52
+ callback.should_receive(:call).once.with do |success, result, key|
53
+ expect(success).to be_true
54
+ expect(result).to be_a(Gecko::Http::Result)
55
+ expect(key).to eq('widget_key1')
56
+ end
57
+ @widget.on_update(&callback)
58
+ @widget.update
59
+ end
60
+
61
+ context 'response object' do
62
+ let(:http_response) { @widget.update.first }
63
+
64
+ it 'should have no errors' do
65
+ expect(http_response.error?).to be_false
66
+ end
67
+ end
68
+
69
+ end
70
+ end
71
+
72
+ context 'Widget with 2 keys, successful response' do
73
+ before(:each) do
74
+ create_widget('widget_key1', 'widget_key2') do
75
+ [200, {}, MultiJson.encode({:success => true})]
76
+ end
77
+ end
78
+
79
+ describe '#update' do
80
+ it 'should return 2 request objects' do
81
+ update_result = @widget.update
82
+ expect(update_result).to be_a(Array)
83
+ expect(update_result).to have(2).items
84
+ update_result.each do |result|
85
+ expect(result).to be_a(Gecko::Http::Result)
86
+ end
87
+ end
88
+
89
+ it 'should evoke callback passed to #update' do
90
+ callback = MockBlock.new
91
+ callback.should_receive(:call).twice.with do |success, result, key|
92
+ expect(success).to be_true
93
+ expect(result).to be_a(Gecko::Http::Result)
94
+ expect(key).to match(/widget_key[1|2]/)
95
+ end
96
+ @widget.update(&callback)
97
+ end
98
+
99
+ it 'should evoke callback passed to #on_update' do
100
+ callback = MockBlock.new
101
+ callback.should_receive(:call).twice.with do |success, result, key|
102
+ expect(success).to be_true
103
+ expect(result).to be_a(Gecko::Http::Result)
104
+ expect(key).to match(/widget_key[1|2]/)
105
+ end
106
+ @widget.on_update(&callback)
107
+ @widget.update
108
+ end
109
+
110
+ context 'response objects' do
111
+ let(:http_responses) { @widget.update }
112
+
113
+ it 'should have no errors' do
114
+ http_responses.each do |http_response|
115
+ expect(http_response.error?).to be_false
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end
121
+
122
+ context 'Widget with 2 keys, errors response' do
123
+ before(:each) do
124
+ create_widget('widget_key1', 'widget_key2') do
125
+ [200, {}, MultiJson.encode({:success => false, :error => 'Push operation failed due to an unknown reason. Please try again!'})]
126
+ end
127
+ end
128
+
129
+ describe '#update' do
130
+ it 'should return 2 request objects' do
131
+ update_result = @widget.update
132
+ expect(update_result).to be_a(Array)
133
+ expect(update_result).to have(2).items
134
+ update_result.each do |result|
135
+ expect(result).to be_a(Gecko::Http::Result)
136
+ end
137
+ end
138
+
139
+ it 'should evoke callback passed to #update' do
140
+ callback = MockBlock.new
141
+ callback.should_receive(:call).twice.with do |success, result, key|
142
+ expect(success).to be_false
143
+ expect(result).to be_a(Gecko::Http::Result)
144
+ expect(key).to match(/widget_key[1|2]/)
145
+ end
146
+ @widget.update(&callback)
147
+ end
148
+
149
+ it 'should evoke callback passed to #on_update' do
150
+ callback = MockBlock.new
151
+ callback.should_receive(:call).twice.with do |success, result, key|
152
+ expect(success).to be_false
153
+ expect(result).to be_a(Gecko::Http::Result)
154
+ expect(key).to match(/widget_key[1|2]/)
155
+ end
156
+ @widget.on_update(&callback)
157
+ @widget.update
158
+ end
159
+
160
+ context 'response objects' do
161
+ let(:http_responses) { @widget.update }
162
+
163
+ it 'should have errors' do
164
+ http_responses.each do |http_response|
165
+ expect(http_response.error?).to be_true
166
+ expect(http_response.error.to_s).to eq('Push operation failed due to an unknown reason. Please try again!')
167
+ end
168
+ end
169
+ end
170
+ end
171
+ end
172
+ end