grifter 0.0.4

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,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: []