keen 0.3.0 → 0.4.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,40 @@
1
+ module Keen
2
+ module HTTP
3
+ class Sync
4
+ def initialize(host, port, options={})
5
+ require 'net/https'
6
+ @http = Net::HTTP.new(host, port)
7
+ options.each_pair { |key, value| @http.send "#{key}=", value }
8
+ end
9
+
10
+ def post(options)
11
+ path, headers, body = options.values_at(
12
+ :path, :headers, :body)
13
+ @http.post(path, body, headers)
14
+ end
15
+ end
16
+
17
+ class Async
18
+ def initialize(host, port, options={})
19
+ if defined?(EventMachine) && EventMachine.reactor_running?
20
+ require 'em-http-request'
21
+ else
22
+ raise Error, "An EventMachine loop must be running to use publish_async calls"
23
+ end
24
+
25
+ @host, @port, @http_options = host, port, options
26
+ end
27
+
28
+ def post(options)
29
+ path, headers, body = options.values_at(
30
+ :path, :headers, :body)
31
+ uri = "https://#{@host}:#{@port}#{path}"
32
+ http_client = EventMachine::HttpRequest.new(uri, @http_options)
33
+ http_client.post(
34
+ :body => body,
35
+ :head => headers
36
+ )
37
+ end
38
+ end
39
+ end
40
+ end
@@ -1,19 +1,3 @@
1
- require 'keen'
2
- require 'yaml'
3
-
4
- # parse VERSION.yml
5
- yaml_path = File.join(File.expand_path(File.dirname(__FILE__)), '..', '..', 'VERSION.yml')
6
- version_info = File.open( yaml_path ) { |file| YAML::load( file ) }
7
-
8
- # build the version string
9
- version_string = ""
10
- version_string += "#{version_info[:major]}"
11
- version_string += "#{version_info[:minor]}"
12
- version_string += "#{version_info[:patch]}"
13
-
14
- if version_info[:build]
15
- version_string += "#{version_info[:build]}"
1
+ module Keen
2
+ VERSION = "0.4.1"
16
3
  end
17
-
18
- # set the constant
19
- Keen::VERSION = version_string
@@ -0,0 +1,63 @@
1
+ require File.expand_path("../spec_helper", __FILE__)
2
+
3
+ describe "Keen IO API" do
4
+ let(:project_id) { ENV['KEEN_PROJECT_ID'] }
5
+ let(:api_key) { ENV['KEEN_API_KEY'] }
6
+
7
+ let(:collection) { "users" }
8
+ let(:event_properties) { { "name" => "Bob" } }
9
+ let(:api_success) { { "created" => true } }
10
+
11
+ describe "success" do
12
+
13
+ it "should return a created status for a valid post" do
14
+ Keen.publish(collection, event_properties).should == api_success
15
+ end
16
+ end
17
+
18
+ describe "failure" do
19
+ it "should raise a not found error if an invalid project id" do
20
+ client = Keen::Client.new(
21
+ :api_key => api_key, :project_id => "riker")
22
+ expect {
23
+ client.publish(collection, event_properties)
24
+ }.to raise_error(Keen::NotFoundError)
25
+ end
26
+
27
+ it "should raise authentication error if invalid API Key" do
28
+ client = Keen::Client.new(
29
+ :api_key => "wrong", :project_id => project_id)
30
+ expect {
31
+ client.publish(collection, event_properties)
32
+ }.to raise_error(Keen::AuthenticationError)
33
+ end
34
+
35
+ it "should raise bad request if no JSON is supplied" do
36
+ expect {
37
+ Keen.publish(collection, nil)
38
+ }.to raise_error(Keen::BadRequestError)
39
+ end
40
+
41
+ it "should return not found for an invalid collection name" do
42
+ expect {
43
+ Keen.publish(nil, event_properties)
44
+ }.to raise_error(Keen::NotFoundError)
45
+ end
46
+ end
47
+
48
+ describe "async" do
49
+ # no TLS support in EventMachine on jRuby
50
+ unless defined?(JRUBY_VERSION)
51
+
52
+ it "should publish the event and trigger callbacks" do
53
+ EM.run {
54
+ Keen.publish_async(collection, event_properties).callback { |response|
55
+ response.should == api_success
56
+ EM.stop
57
+ }
58
+ }
59
+ end
60
+
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,8 @@
1
+ require File.expand_path("../../spec_helper", __FILE__)
2
+
3
+ RSpec.configure do |config|
4
+ unless ENV['KEEN_PROJECT_ID'] && ENV['KEEN_API_KEY']
5
+ raise "Please set a KEEN_PROJECT_ID and KEEN_API_KEY on the environment
6
+ before running the integration specs."
7
+ end
8
+ end
@@ -0,0 +1,191 @@
1
+ require File.expand_path("../spec_helper", __FILE__)
2
+
3
+ describe Keen::Client do
4
+ let(:project_id) { "12345" }
5
+ let(:api_key) { "abcde" }
6
+ let(:collection) { "users" }
7
+ let(:event_properties) { { "name" => "Bob" } }
8
+ let(:api_success) { { "created" => true } }
9
+
10
+ def stub_api(url, status, json_body)
11
+ stub_request(:post, url).to_return(
12
+ :status => status,
13
+ :body => MultiJson.encode(json_body))
14
+ end
15
+
16
+ def expect_post(url, event_properties, api_key)
17
+ WebMock.should have_requested(:post, url).with(
18
+ :body => MultiJson.encode(event_properties),
19
+ :headers => { "Content-Type" => "application/json",
20
+ "User-Agent" => "keen-gem v#{Keen::VERSION}",
21
+ "Authorization" => api_key })
22
+ end
23
+
24
+ def api_url(collection)
25
+ "https://api.keen.io/3.0/projects/#{project_id}/events/#{collection}"
26
+ end
27
+
28
+ describe "#initialize" do
29
+ context "deprecated" do
30
+ it "should allow created via project_id and api_key args" do
31
+ client = Keen::Client.new(project_id, api_key)
32
+ client.api_key.should == api_key
33
+ client.project_id.should == project_id
34
+ end
35
+ end
36
+
37
+ it "should initialize with options" do
38
+ client = Keen::Client.new(
39
+ :project_id => project_id,
40
+ :api_key => api_key)
41
+ client.api_key.should == api_key
42
+ client.project_id.should == project_id
43
+ end
44
+ end
45
+
46
+ describe "with a unconfigured client" do
47
+ [:publish, :publish_async].each do |_method|
48
+ describe "##{_method}" do
49
+ it "should raise an exception if no project_id" do
50
+ expect {
51
+ Keen::Client.new(:api_key => api_key).
52
+ send(_method, collection, event_properties)
53
+ }.to raise_error(Keen::ConfigurationError)
54
+ end
55
+
56
+ it "should raise an exception if no api_key" do
57
+ expect {
58
+ Keen::Client.new(:project_id => project_id).
59
+ send(_method, collection, event_properties)
60
+ }.to raise_error(Keen::ConfigurationError)
61
+ end
62
+ end
63
+ end
64
+ end
65
+
66
+ describe "with a configured client" do
67
+ before do
68
+ @client = Keen::Client.new(
69
+ :project_id => project_id,
70
+ :api_key => api_key)
71
+ end
72
+
73
+ describe "#publish" do
74
+ it "should post using the collection and properties" do
75
+ stub_api(api_url(collection), 201, "")
76
+ @client.publish(collection, event_properties)
77
+ expect_post(api_url(collection), event_properties, api_key)
78
+ end
79
+
80
+ it "should return the proper response" do
81
+ api_response = { "created" => true }
82
+ stub_api(api_url(collection), 201, api_response)
83
+ @client.publish(collection, event_properties).should == api_response
84
+ end
85
+
86
+ it "should wrap exceptions" do
87
+ stub_request(:post, api_url(collection)).to_timeout
88
+ e = nil
89
+ begin
90
+ @client.publish(collection, event_properties)
91
+ rescue Exception => exception
92
+ e = exception
93
+ end
94
+
95
+ e.class.should == Keen::HttpError
96
+ e.original_error.class.should == Timeout::Error
97
+ e.message.should == "Couldn't connect to Keen IO: execution expired"
98
+ end
99
+ end
100
+
101
+ describe "#publish_async" do
102
+
103
+ # no TLS support in EventMachine on jRuby
104
+ unless defined?(JRUBY_VERSION)
105
+ it "should require a running event loop" do
106
+ expect {
107
+ @client.publish_async(collection, event_properties)
108
+ }.to raise_error(Keen::Error)
109
+ end
110
+
111
+ it "should post the event data" do
112
+ stub_api(api_url(collection), 201, api_success)
113
+ EM.run {
114
+ @client.publish_async(collection, event_properties).callback {
115
+ expect_post(api_url(collection), event_properties, api_key)
116
+ EM.stop
117
+ }
118
+ }
119
+ end
120
+
121
+ describe "deferrable callbacks" do
122
+ it "should trigger callbacks" do
123
+ stub_api(api_url(collection), 201, api_success)
124
+ EM.run {
125
+ @client.publish_async(collection, event_properties).callback { |response|
126
+ response.should == api_success
127
+ EM.stop
128
+ }
129
+ }
130
+ end
131
+
132
+ it "should trigger errbacks" do
133
+ stub_request(:post, api_url(collection)).to_timeout
134
+ EM.run {
135
+ @client.publish_async(collection, event_properties).errback { |error|
136
+ error.should_not be_nil
137
+ error.message.should == "Couldn't connect to Keen IO: WebMock timeout error"
138
+ EM.stop
139
+ }
140
+ }
141
+ end
142
+ end
143
+ end
144
+
145
+ end
146
+
147
+ describe "response handling" do
148
+ def stub_status_and_publish(code, api_response=nil)
149
+ stub_api(api_url(collection), code, api_response)
150
+ @client.publish(collection, event_properties)
151
+ end
152
+
153
+ it "should return the json body for a 200-201" do
154
+ api_response = { "created" => "true" }
155
+ stub_status_and_publish(200, api_response).should == api_response
156
+ stub_status_and_publish(201, api_response).should == api_response
157
+ end
158
+
159
+ it "should raise a bad request error for a 400" do
160
+ expect {
161
+ stub_status_and_publish(400)
162
+ }.to raise_error(Keen::BadRequestError)
163
+ end
164
+
165
+ it "should raise a authentication error for a 401" do
166
+ expect {
167
+ stub_status_and_publish(401)
168
+ }.to raise_error(Keen::AuthenticationError)
169
+ end
170
+
171
+ it "should raise a not found error for a 404" do
172
+ expect {
173
+ stub_status_and_publish(404)
174
+ }.to raise_error(Keen::NotFoundError)
175
+ end
176
+
177
+ it "should raise an http error otherwise" do
178
+ expect {
179
+ stub_status_and_publish(420)
180
+ }.to raise_error(Keen::HttpError)
181
+ end
182
+ end
183
+
184
+ describe "#add_event" do
185
+ it "should alias to publish" do
186
+ @client.should_receive(:publish).with("users", {:a => 1}, {:b => 2})
187
+ @client.add_event("users", {:a => 1}, {:b => 2})
188
+ end
189
+ end
190
+ end
191
+ end
@@ -0,0 +1,61 @@
1
+ require File.expand_path("../spec_helper", __FILE__)
2
+
3
+ describe Keen do
4
+ describe "default client" do
5
+ describe "configuring from the environment" do
6
+ before do
7
+ ENV["KEEN_PROJECT_ID"] = "12345"
8
+ ENV["KEEN_API_KEY"] = "abcde"
9
+ end
10
+
11
+ let(:client) { Keen.send(:default_client) }
12
+
13
+ it "should set a project id from the environment" do
14
+ client.project_id.should == "12345"
15
+ end
16
+
17
+ it "should set a project id from the environment" do
18
+ client.api_key.should == "abcde"
19
+ end
20
+
21
+ after do
22
+ ENV["KEEN_PROJECT_ID"] = nil
23
+ ENV["KEEN_API_KEY"] = nil
24
+ end
25
+ end
26
+ end
27
+
28
+ describe "forwardable" do
29
+ before do
30
+ @default_client = double("client")
31
+ Keen.stub(:default_client).and_return(@default_client)
32
+ end
33
+
34
+ [:project_id, :api_key].each do |_method|
35
+ it "should forward the #{_method} method" do
36
+ @default_client.should_receive(_method)
37
+ Keen.send(_method)
38
+ end
39
+ end
40
+
41
+ [:project_id=, :api_key=].each do |_method|
42
+ it "should forward the #{_method} method" do
43
+ @default_client.should_receive(_method).with("12345")
44
+ Keen.send(_method, "12345")
45
+ end
46
+ end
47
+
48
+ [:publish, :publish_async].each do |_method|
49
+ it "should forward the #{_method} method" do
50
+ @default_client.should_receive(_method).with("users", {})
51
+ Keen.send(_method, "users", {})
52
+ end
53
+ end
54
+ end
55
+
56
+ describe "logger" do
57
+ it "should be set to info" do
58
+ Keen.logger.level.should == Logger::INFO
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,10 @@
1
+ require File.expand_path("../../spec_helper", __FILE__)
2
+
3
+ require 'webmock/rspec'
4
+
5
+ RSpec.configure do |config|
6
+ config.before(:each) do
7
+ WebMock.disable_net_connect!
8
+ WebMock.reset!
9
+ end
10
+ end
@@ -0,0 +1,16 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'Use of Bundler is recommended'
5
+ end
6
+
7
+ require 'rspec'
8
+ require 'net/https'
9
+ require 'em-http'
10
+
11
+ require File.expand_path("../../lib/keen", __FILE__)
12
+
13
+ RSpec.configure do |config|
14
+ config.before(:all) do
15
+ end
16
+ end
metadata CHANGED
@@ -1,153 +1,87 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: keen
3
- version: !ruby/object:Gem::Version
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.1
4
5
  prerelease:
5
- version: 0.3.0
6
6
  platform: ruby
7
- authors:
8
- - dorkitude
7
+ authors:
8
+ - Kyle Wild
9
+ - Josh Dzielak
9
10
  autorequire:
10
11
  bindir: bin
11
12
  cert_chain: []
12
-
13
- date: 2012-11-26 00:00:00 Z
14
- dependencies:
15
- - !ruby/object:Gem::Dependency
16
- name: json
17
- requirement: &id001 !ruby/object:Gem::Requirement
13
+ date: 2013-01-07 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: multi_json
17
+ requirement: !ruby/object:Gem::Requirement
18
18
  none: false
19
- requirements:
20
- - - ">="
21
- - !ruby/object:Gem::Version
22
- version: 1.6.5
23
- type: :runtime
24
- prerelease: false
25
- version_requirements: *id001
26
- - !ruby/object:Gem::Dependency
27
- name: shoulda
28
- requirement: &id002 !ruby/object:Gem::Requirement
29
- none: false
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: "0"
34
- type: :development
35
- prerelease: false
36
- version_requirements: *id002
37
- - !ruby/object:Gem::Dependency
38
- name: rdoc
39
- requirement: &id003 !ruby/object:Gem::Requirement
40
- none: false
41
- requirements:
19
+ requirements:
42
20
  - - ~>
43
- - !ruby/object:Gem::Version
44
- version: "3.12"
45
- type: :development
46
- prerelease: false
47
- version_requirements: *id003
48
- - !ruby/object:Gem::Dependency
49
- name: bundler
50
- requirement: &id004 !ruby/object:Gem::Requirement
51
- none: false
52
- requirements:
53
- - - ">="
54
- - !ruby/object:Gem::Version
55
- version: 1.1.4
56
- type: :development
21
+ - !ruby/object:Gem::Version
22
+ version: '1.0'
23
+ type: :runtime
57
24
  prerelease: false
58
- version_requirements: *id004
59
- - !ruby/object:Gem::Dependency
60
- name: jeweler
61
- requirement: &id005 !ruby/object:Gem::Requirement
25
+ version_requirements: !ruby/object:Gem::Requirement
62
26
  none: false
63
- requirements:
27
+ requirements:
64
28
  - - ~>
65
- - !ruby/object:Gem::Version
66
- version: 1.8.3
67
- type: :development
68
- prerelease: false
69
- version_requirements: *id005
70
- - !ruby/object:Gem::Dependency
71
- name: rspec
72
- requirement: &id006 !ruby/object:Gem::Requirement
73
- none: false
74
- requirements:
75
- - - ">="
76
- - !ruby/object:Gem::Version
77
- version: 2.9.0
78
- type: :development
79
- prerelease: false
80
- version_requirements: *id006
81
- - !ruby/object:Gem::Dependency
82
- name: cucumber
83
- requirement: &id007 !ruby/object:Gem::Requirement
84
- none: false
85
- requirements:
86
- - - ">="
87
- - !ruby/object:Gem::Version
88
- version: 1.2.1
89
- type: :development
90
- prerelease: false
91
- version_requirements: *id007
92
- description: See the github repo or examples.rb for usage information.
93
- email: kyle@keen.io
29
+ - !ruby/object:Gem::Version
30
+ version: '1.0'
31
+ description: Batch and send events to the Keen IO API. Supports asychronous requests.
32
+ email: josh@keen.io
94
33
  executables: []
95
-
96
34
  extensions: []
97
-
98
- extra_rdoc_files:
99
- - LICENSE.txt
100
- - README.md
101
- files:
102
- - .rvmrc
35
+ extra_rdoc_files: []
36
+ files:
37
+ - .gitignore
38
+ - .rspec
39
+ - .travis.yml
103
40
  - Gemfile
104
- - LICENSE.txt
41
+ - Guardfile
42
+ - LICENSE
105
43
  - README.md
106
44
  - Rakefile
107
- - VERSION.yml
108
- - conf/cacert.pem
109
- - examples.rb
110
- - features/add_event.feature
111
- - features/step_definitions/keen_steps.rb
112
- - features/support/before_and_after.rb
113
- - features/support/env.rb
45
+ - config/cacert.pem
114
46
  - keen.gemspec
115
- - keen.gemspec.old
116
47
  - lib/keen.rb
117
48
  - lib/keen/client.rb
118
- - lib/keen/event.rb
119
- - lib/keen/keys.rb
120
- - lib/keen/utils.rb
49
+ - lib/keen/http.rb
121
50
  - lib/keen/version.rb
122
- homepage: http://github.com/dorkitude/keen
123
- licenses:
124
- - MIT
51
+ - spec/integration/api_spec.rb
52
+ - spec/integration/spec_helper.rb
53
+ - spec/keen/client_spec.rb
54
+ - spec/keen/keen_spec.rb
55
+ - spec/keen/spec_helper.rb
56
+ - spec/spec_helper.rb
57
+ homepage: https://github.com/keenlabs/keen-gem
58
+ licenses: []
125
59
  post_install_message:
126
60
  rdoc_options: []
127
-
128
- require_paths:
61
+ require_paths:
129
62
  - lib
130
- required_ruby_version: !ruby/object:Gem::Requirement
63
+ required_ruby_version: !ruby/object:Gem::Requirement
131
64
  none: false
132
- requirements:
133
- - - ">="
134
- - !ruby/object:Gem::Version
135
- hash: -1792663848985586478
136
- segments:
137
- - 0
138
- version: "0"
139
- required_rubygems_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ! '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ required_rubygems_version: !ruby/object:Gem::Requirement
140
70
  none: false
141
- requirements:
142
- - - ">="
143
- - !ruby/object:Gem::Version
144
- version: "0"
71
+ requirements:
72
+ - - ! '>='
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
145
75
  requirements: []
146
-
147
76
  rubyforge_project:
148
- rubygems_version: 1.8.19
77
+ rubygems_version: 1.8.23
149
78
  signing_key:
150
79
  specification_version: 3
151
- summary: A library for batching and sending arbitrary events to the Keen API at http://keen.io
152
- test_files: []
153
-
80
+ summary: Keen IO API Client
81
+ test_files:
82
+ - spec/integration/api_spec.rb
83
+ - spec/integration/spec_helper.rb
84
+ - spec/keen/client_spec.rb
85
+ - spec/keen/keen_spec.rb
86
+ - spec/keen/spec_helper.rb
87
+ - spec/spec_helper.rb