grifter 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,127 @@
1
+ require 'grifter/configuration'
2
+
3
+ describe Grifter::Configuration do
4
+
5
+ let(:configuration) { Class.new.extend(Grifter::Configuration) }
6
+
7
+ let(:empty_config) { {} }
8
+
9
+ let (:no_service_config) { { services: {} } }
10
+
11
+ let (:single_basic_service_config) {
12
+ {
13
+ services: {
14
+ twitter: { hostname: 'twitter.com' }
15
+ }
16
+ }
17
+ }
18
+
19
+ let (:all_service_values_defined) {
20
+ {
21
+ services: {
22
+ twitter: {
23
+ hostname: 'twitter.com',
24
+ port: 8888,
25
+ ssl: true,
26
+ ignore_ssl_cert: true,
27
+ base_uri: '/api/v2',
28
+ }
29
+ }
30
+ }
31
+ }
32
+
33
+ describe "Service configuration normalization" do
34
+ it "should require a services block" do
35
+ expect { configuration.normalize_config empty_config }.to raise_error GrifterConfigurationError
36
+ end
37
+
38
+ it "should require at least one service in service block" do
39
+ expect { configuration.normalize_config no_service_config }.to raise_error GrifterConfigurationError
40
+ end
41
+
42
+ it "should default ssl, ssl_certificate_ignore, and port" do
43
+ config = configuration.normalize_config single_basic_service_config
44
+ config[:services].should eql({
45
+ twitter: {
46
+ hostname: 'twitter.com',
47
+ port: 80,
48
+ ssl: false,
49
+ ignore_ssl_cert: false,
50
+ base_uri: '',
51
+ name: 'twitter',
52
+ }}
53
+ )
54
+ end
55
+
56
+ it "should allow overrides for all values" do
57
+ config = configuration.normalize_config all_service_values_defined
58
+ config.should eql(all_service_values_defined)
59
+ end
60
+ end
61
+
62
+ describe "loading config from a file" do
63
+ it "should allow specifying a filename" do
64
+ config = configuration.load_config_file config_file: 'spec/resources/example_config.yml'
65
+ config[:services].should eql({
66
+ myapi: {
67
+ hostname: 'myapi.com',
68
+ name: 'myapi',
69
+ port: 80,
70
+ ssl: false,
71
+ ignore_ssl_cert: false,
72
+ base_uri: '',
73
+ },
74
+ myotherapi: {
75
+ hostname: 'myotherapi.com',
76
+ name: 'myotherapi',
77
+ port: 80,
78
+ ssl: false,
79
+ ignore_ssl_cert: false,
80
+ base_uri: '',
81
+ },
82
+ })
83
+ end
84
+
85
+ it "should take the filename from an environment variable if specified" do
86
+ ENV['GRIFTER_CONFIG_FILE'] = 'spec/resources/example_config.yml'
87
+ config = configuration.load_config_file
88
+ config[:services].keys.should =~ [:myapi, :myotherapi]
89
+ ENV['GRIFTER_CONFIG_FILE'] = nil
90
+ end
91
+ end
92
+
93
+ describe "environment based overriding" do
94
+ it "should allow overriding configuration based on an environment name" do
95
+ config = configuration.load_config_file config_file: 'spec/resources/example_config.yml',
96
+ environment: :dev
97
+ config[:services].should eql({
98
+ myapi: {
99
+ hostname: 'dev.myapi.com',
100
+ name: 'myapi',
101
+ port: 123,
102
+ ssl: false,
103
+ ignore_ssl_cert: false,
104
+ base_uri: '',
105
+ },
106
+ myotherapi: {
107
+ hostname: 'myotherapi.com',
108
+ name: 'myotherapi',
109
+ port: 80,
110
+ ssl: false,
111
+ ignore_ssl_cert: false,
112
+ base_uri: '',
113
+ },
114
+ })
115
+
116
+ end
117
+
118
+ it "should allow setting environment via an environment variable" do
119
+ ENV['GRIFTER_ENVIRONMENT'] = 'dev'
120
+ config = configuration.load_config_file config_file: 'spec/resources/example_config.yml'
121
+
122
+ config[:services][:myapi][:hostname].should eql 'dev.myapi.com'
123
+ ENV['GRIFTER_ENVIRONMENT'] = nil
124
+
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,52 @@
1
+ require 'grifter'
2
+
3
+ describe Grifter do
4
+ describe "Configuration" do
5
+ it "should allow for initializing from a config file" do
6
+ grifter = Grifter.new :config_file => 'spec/resources/example_config.yml'
7
+ grifter.should respond_to(:myapi)
8
+ grifter.myapi.name.should eql('myapi')
9
+ grifter.services.any?{|s| s.name == 'myapi' }.should be_true
10
+
11
+ grifter.should respond_to(:myotherapi)
12
+ grifter.myotherapi.name.should eql('myotherapi')
13
+ grifter.services.any?{|s| s.name == 'myotherapi' }.should be_true
14
+ end
15
+ end
16
+
17
+ describe "Grifter files" do
18
+ it "should allow loading grifter files which define methods for interacting with apis" do
19
+ grifter = Grifter.new :config_file => 'spec/resources/grifter.yml'
20
+ grifter.should respond_to :timeline_for
21
+ end
22
+
23
+ describe "syntax errors" do
24
+ it "should produce a nice stack trace if a grifter file has a syntax error" do
25
+ expect do
26
+ grifter = Grifter.new load_from_config_file: false,
27
+ grift_globs: ['spec/resources/syntax_error_grifts/eval_error_grifts.rb']
28
+ end.to raise_error NoMethodError
29
+ end
30
+ end
31
+ end
32
+
33
+ describe "Authentication" do
34
+ it "when authenticate is invoked, it should call any method ending in grifter_authenticate" do
35
+ grifter = Grifter.new :config_file => 'spec/resources/example_config.yml'
36
+ grifter.define_singleton_method :test_svc_grifter_authenticate do
37
+ true
38
+ end
39
+ grifter.define_singleton_method :test_svc_grifter_authenticate_substring_only do
40
+ true
41
+ end
42
+
43
+ grifter.should_receive :test_svc_grifter_authenticate
44
+ grifter.should_not_receive :test_svc_grifter_authenticate_substring_only
45
+
46
+ grifter.grifter_authenticate_do
47
+ end
48
+
49
+ #TODO: test that ensures grifter_authenticate_do is called
50
+ # if Grifter is instantiated with :authenticate => true
51
+ end
52
+ end
@@ -0,0 +1,81 @@
1
+ require 'grifter/http_service'
2
+
3
+ describe Grifter::HTTPService do
4
+
5
+ let(:test_configuration) do
6
+ {
7
+ name: 'test service',
8
+ hostname: 'totallyfakedomainthatcouldnotpossiblyexist.com',
9
+ port: 80,
10
+ ssl: false,
11
+ ignore_ssl_certificate: false,
12
+ }
13
+ end
14
+
15
+ before(:each) do
16
+ @svc = Grifter::HTTPService.new test_configuration
17
+ end
18
+
19
+ describe "http methods" do
20
+ before(:each) do
21
+ response = Net::HTTPOK.new('1.1', 200, "stub response body")
22
+ response.stub(:body).and_return '{"foo": "bar"}'
23
+ @svc.http.stub!(:request).and_return(response)
24
+ end
25
+
26
+ #methods without a request body
27
+ [
28
+ :get,
29
+ :head,
30
+ :delete,
31
+ ].each do |method|
32
+ it "should have a #{method.to_s} method" do
33
+ @svc.send(method, '/testing').should be_a Hash
34
+ end
35
+ end
36
+
37
+ #methods with a json request body
38
+ [
39
+ :put,
40
+ :post,
41
+ ].each do |method|
42
+ it "should have a #{method.to_s} method" do
43
+ @svc.send(method, '/testing', {'a_key' => 'a_value'}).should be_a Hash
44
+ end
45
+ end
46
+
47
+ it "should remember the last request and response" do
48
+ @svc.post '/testing', 'a_key' => 'a_value'
49
+ @svc.last_request.should be_a Net::HTTP::Post
50
+ @svc.last_response.should be_a Net::HTTPOK
51
+ end
52
+ end
53
+
54
+ describe "error handling" do
55
+ before(:each) do
56
+ response = Net::HTTPBadRequest.new('1.1', 400, "stuff not sure what it does")
57
+ response.stub(:body).and_return '{"error_code": "400", "error_message": "bad api client, no cookies for you!"}'
58
+ @svc.http.stub!(:request).and_return(response)
59
+ end
60
+
61
+ it "should raise a RequestException when a 400 is returned" do
62
+ expect { @svc.get '/testing' }.to raise_error(Grifter::RequestException)
63
+ end
64
+ end
65
+
66
+ describe "default header configuration" do
67
+ it "should specification of default headers" do
68
+ svc = Grifter::HTTPService.new test_configuration.merge default_headers: { 'abc' => '123' }
69
+ response = Net::HTTPOK.new('1.1', 200, "stub response body")
70
+ response.stub(:body).and_return '{"foo": "bar"}'
71
+ svc.http.stub!(:request).and_return(response)
72
+
73
+ svc.http.should_receive(:request).with do |req|
74
+ req['abc'].should eql('123')
75
+ end
76
+
77
+ svc.get '/hello'
78
+
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,53 @@
1
+ require 'grifter/json_helpers.rb'
2
+
3
+ describe Grifter::JsonHelpers do
4
+
5
+ let(:json_helper) { Class.new.extend(Grifter::JsonHelpers) }
6
+
7
+ describe :jsonify do
8
+ it "should turn a hash into json" do
9
+ hash = {
10
+ 'a' => '123',
11
+ 'b' => 456,
12
+ :c => [
13
+ 1,
14
+ 2.3,
15
+ '456'
16
+ ],
17
+ 'd' => {
18
+ 'x' => 'y'
19
+ }
20
+ }
21
+
22
+ json = json_helper.jsonify(hash)
23
+
24
+ #ugh, gross!
25
+ json.should eql %Q|{
26
+ "a": "123",
27
+ "b": 456,
28
+ "c": [
29
+ 1,
30
+ 2.3,
31
+ "456"
32
+ ],
33
+ "d": {
34
+ "x": "y"
35
+ }
36
+ }|
37
+
38
+ end
39
+
40
+ it "should return a non json string as itself" do
41
+ json_helper.jsonify("abc").should eql("abc")
42
+ end
43
+
44
+ it "should make a json string pretty" do
45
+ json_str = '{"foo":"bar", "abc":123}'
46
+ json_helper.jsonify(json_str).should eql %Q|{
47
+ "foo": "bar",
48
+ "abc": 123
49
+ }|
50
+ end
51
+
52
+ end
53
+ end
@@ -0,0 +1,19 @@
1
+ ---
2
+ services:
3
+ myapi:
4
+ hostname: 'myapi.com'
5
+
6
+ myotherapi:
7
+ hostname: 'myotherapi.com'
8
+
9
+ environments:
10
+ dev:
11
+ myapi:
12
+ hostname: 'dev.myapi.com'
13
+ port: 123
14
+
15
+ staging:
16
+ myapi:
17
+ hostname: 'staging.myapi.com'
18
+ port: 456
19
+ ignore_ssl_cert: true
@@ -0,0 +1,11 @@
1
+ #base configuration of services goes here
2
+ services:
3
+ twitter:
4
+ hostname: 'api.twitter.com'
5
+ port: 443
6
+ ssl: true
7
+ ignore_ssl_cert: false
8
+ base_uri: '/1.1'
9
+
10
+ grift_globs:
11
+ - 'spec/resources/twitter_grifts/**/*_grifts.rb'
@@ -0,0 +1,23 @@
1
+ require 'base64'
2
+
3
+ def twitter_keys
4
+ @_twitter_keys ||= YAML.load_file('example/twitter_grifts/oauth.yml')
5
+ end
6
+
7
+ def application_authenticate
8
+ params = { 'grant_type' => 'client_credentials' }
9
+ token = twitter_keys['consumer_key'] + ':' + twitter_keys['consumer_secret']
10
+ encoded_token = Base64.strict_encode64(token)
11
+ response = twitter.post_form '/oauth2/token', params,
12
+ base_uri: '',
13
+ additional_headers: {
14
+ 'Authorization' => "Basic " + encoded_token,
15
+ 'Accept' => '*/*', # I think this is a bug that I have to set it to this: https://dev.twitter.com/discussions/16348#comment-36465
16
+ }
17
+ twitter.headers['Authorization'] = "Bearer #{response['access_token']}"
18
+ true
19
+ end
20
+
21
+ def twitter_grift
22
+ application_authenticate
23
+ end
@@ -0,0 +1,9 @@
1
+
2
+ def timeline_for screen_name
3
+ response = twitter.get "/statuses/user_timeline.json?screen_name=#{screen_name}&count=100"
4
+ end
5
+
6
+ def status_list screen_name
7
+ timeline = timeline_for screen_name
8
+ timeline.map {|status| status['text']}
9
+ end
@@ -0,0 +1,30 @@
1
+ require 'grifter'
2
+ require 'grifter/helpers'
3
+
4
+ describe Grifter::Helpers do
5
+ describe "including" do
6
+ it "should be includable" do
7
+ mod = Module.new do
8
+ ENV['GRIFTER_CONFIG_FILE'] = 'spec/resources/grifter.yml'
9
+ include Grifter::Helpers
10
+ end
11
+
12
+ cla = Class.new do
13
+ extend mod
14
+ end
15
+
16
+ cla.should respond_to :grifter
17
+
18
+ #should return the grifter instance if requested
19
+ cla.grifter.should be_a Grifter
20
+ cla.grifter.should respond_to :timeline_for
21
+
22
+ #but better, all grift methods are just available as is
23
+ cla.should respond_to :timeline_for
24
+
25
+ #the raw services should be available
26
+ cla.should respond_to :twitter
27
+ cla.twitter.should respond_to :get
28
+ end
29
+ end
30
+ end
File without changes
@@ -0,0 +1,19 @@
1
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
2
+ RSpec.configure do |config|
3
+ #config.treat_symbols_as_metadata_keys_with_true_values = true
4
+
5
+ #setting this to false ensure if we screw up a tag, nothing will run
6
+ # and we'll know a tag is screwed up.
7
+ config.run_all_when_everything_filtered = false
8
+
9
+ # removing this bit of config as it will interfere with our custom tagging scheme
10
+ #config.filter_run :focus
11
+
12
+ # Run specs in random order to surface order dependencies. If you find an
13
+ # order dependency and want to debug it, you can fix the order by providing
14
+ # the seed, which is printed after each run.
15
+ # --seed 1234
16
+ # config.order = 'random'
17
+
18
+ #config.include TestDataHelpers
19
+ end
metadata ADDED
@@ -0,0 +1,159 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: grifter
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.4
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Robert Schultheis
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-05-09 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: json
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rspec
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: pry
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: awesome_print
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: jeweler
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ description: convention based approach to interfacing with an HTTP JSON API.
95
+ email: rob@knewton.com
96
+ executables:
97
+ - grift
98
+ extensions: []
99
+ extra_rdoc_files:
100
+ - LICENSE.txt
101
+ files:
102
+ - Gemfile
103
+ - LICENSE.txt
104
+ - Rakefile
105
+ - Readme.md
106
+ - VERSION
107
+ - bin/grift
108
+ - example/grifter.yml
109
+ - example/owm_grifts/weather_grifts.rb
110
+ - example/temperatures.rb
111
+ - grifter.gemspec
112
+ - lib/grifter.rb
113
+ - lib/grifter/blankslate.rb
114
+ - lib/grifter/configuration.rb
115
+ - lib/grifter/helpers.rb
116
+ - lib/grifter/http_service.rb
117
+ - lib/grifter/json_helpers.rb
118
+ - lib/grifter/log.rb
119
+ - spec/configuration_spec.rb
120
+ - spec/grifter_spec.rb
121
+ - spec/http_service_spec.rb
122
+ - spec/json_helpers_spec.rb
123
+ - spec/resources/example_config.yml
124
+ - spec/resources/grifter.yml
125
+ - spec/resources/syntax_error_grifts/eval_error_grifts.rb
126
+ - spec/resources/twitter_grifts/oauth_grifts.rb
127
+ - spec/resources/twitter_grifts/timeline_grifts.rb
128
+ - spec/rspec_helper_spec.rb
129
+ - spec/support/require_all_lib_files.rb
130
+ - spec/support/spec_helper.rb
131
+ homepage: http://github.com/knewton/grifter
132
+ licenses:
133
+ - MIT
134
+ post_install_message:
135
+ rdoc_options: []
136
+ require_paths:
137
+ - lib
138
+ required_ruby_version: !ruby/object:Gem::Requirement
139
+ none: false
140
+ requirements:
141
+ - - ! '>='
142
+ - !ruby/object:Gem::Version
143
+ version: '0'
144
+ segments:
145
+ - 0
146
+ hash: 95742656892023611
147
+ required_rubygems_version: !ruby/object:Gem::Requirement
148
+ none: false
149
+ requirements:
150
+ - - ! '>='
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ requirements: []
154
+ rubyforge_project:
155
+ rubygems_version: 1.8.24
156
+ signing_key:
157
+ specification_version: 3
158
+ summary: Make calls to HTTP JSON APIs with ease and confidence
159
+ test_files: []