litmus-infrastructure 0.2.6

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 30fb2b926c21f50121d2cdd666cb1a456d3c164b7597f8033057eed7a259c248
4
+ data.tar.gz: '080135fdc2d1401975b9feeefac484bb0ff8c6571364a5f42966b72215b03ebf'
5
+ SHA512:
6
+ metadata.gz: 9a329aaadac90d160ce5140fb23e8fd43c483aeca0bc839c28614b02c805d14279b16d6c4157982f488764e001f7f29ec7c1ada3ea8866210194fe42add884d2
7
+ data.tar.gz: a57934588f013a3d9495ee337b79feefafefc5610153190481508c514512d765bc8d4ca8a784943d36712424c010141884219a281003e12463feb6466d55aab4
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ .DS_Store
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.7.2
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in litmus-infrastructure.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Kevin Thompson
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,76 @@
1
+ # Litmus::Infrastructure
2
+
3
+ A gem that provides an interface between a Ruby application and the Litmus
4
+ infrastructure API.
5
+
6
+ ## Installation
7
+
8
+ If your production environment will have access to this repo (a user on your production server must have an ssh key that corresponds to a user with access to this repo), you can declare the gem in your gemfile using the `github` parameter:
9
+
10
+ ``` ruby
11
+ gem 'litmus-infrastructure', github: 'litmus/litmus-infrastructure-client'
12
+ ```
13
+
14
+ If you do not have access to the SSH keys in your production environment, when using Heroku for example, you'll need to use a repo URL that includes the API key for a user with access to this repo:
15
+
16
+ ``` ruby
17
+ gem 'litmus-infrastructure', git: 'https://GITHUB_API_KEY_XXXXXX@github.com/litmus/litmus-infrastructure-client.git'
18
+ ```
19
+
20
+ ## Usage
21
+
22
+ ### Rails
23
+
24
+ Include `Litmus::Infrastructure` in a module that you'd like to have interact
25
+ with the infrastructure API:
26
+
27
+ ``` ruby
28
+ module Checklist
29
+ include Litmus::Infrastructure
30
+ end
31
+ ```
32
+
33
+ Your integration should be configured by creating an initializer:
34
+
35
+ ``` ruby
36
+ Checklist.configure do |config|
37
+ config.timeout_connect = 5.seconds
38
+ config.timeout_receive = 1.minute
39
+ config.username = ENV['INFRASTRUCTURE_USERNAME']
40
+ config.password = ENV['INFRASTRUCTURE_PASSWORD']
41
+ config.url = ENV['INFRASTRUCTURE_API_BASE_URL']
42
+ config.logger = Rails.logger
43
+ end
44
+ ```
45
+
46
+ Any objects that should act as models for data from the infrastructure API
47
+ should extend `Litmus::Infrastructure::Model`:
48
+
49
+ ``` ruby
50
+ module Checklist
51
+ class Result < Litmus::Infrastructure::Model
52
+ # ...
53
+ end
54
+ end
55
+ ```
56
+
57
+ Your models can define attributes to read from the API using the `attributes`
58
+ class method:
59
+
60
+ ``` ruby
61
+ module Checklist
62
+ class Result < Litmus::Infrastructure::Model
63
+ attributes :content, :encoding, :from, :grade, :images
64
+ # ...
65
+ end
66
+ end
67
+ ```
68
+
69
+ Once your models are defined, you can interact with the infrastructure API using
70
+ the class methods `put`, `post`, and `get`, passing the appropriate
71
+ endpoint/action to these methods as the first parameter, and the JSON payload as
72
+ the second:
73
+
74
+ ``` ruby
75
+ Checklist::Result.post('Checklist', { subject: 'Example' }.to_json)
76
+ ```
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task default: :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "litmus/infrastructure"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/rake ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'rake' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('rake', 'rake')
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,31 @@
1
+ module Litmus
2
+ module Infrastructure
3
+ module Base
4
+
5
+ def self.included(base)
6
+ base.extend(ClassMethods)
7
+ end
8
+
9
+ module ClassMethods
10
+ def namespace
11
+ @namespace ||= parents.find do |mod|
12
+ mod.included_modules.include?(Litmus::Infrastructure)
13
+ end
14
+ end
15
+
16
+ def client
17
+ namespace.http_client
18
+ end
19
+
20
+ def config
21
+ namespace.configuration
22
+ end
23
+
24
+ def logger
25
+ config.logger
26
+ end
27
+ end
28
+
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,30 @@
1
+ require 'logger'
2
+
3
+ module Litmus
4
+ module Infrastructure #:nodoc:
5
+
6
+ # Configuration options for Litmus Infrastructure APIs.
7
+ #
8
+ # == Attributes
9
+ #
10
+ # * <tt>username</tt> - Your username for the Litmus Infrastructure API
11
+ # * <tt>password</tt> - Your password for the Litmus Infrastructure API
12
+ # * <tt>logger</tt> - A Logger instance. Defaults to <tt>Logger.new(STDOUT)</tt>.
13
+ #
14
+ # == Example
15
+ # Litmus::Infrastructure.configure do |config|
16
+ # config.username = 'yourusername'
17
+ # config.password = 'yourpassword'
18
+ # config.logger = Rails.logger
19
+ # end
20
+ class Configuration
21
+ attr_accessor :timeout_connect, :timeout_receive, :url, :username, :password
22
+ attr_writer :url, :logger
23
+
24
+ def logger
25
+ @logger ||= ::Logger.new(STDOUT)
26
+ end
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,23 @@
1
+ module Litmus
2
+ module Infrastructure
3
+ module DataFormatter
4
+
5
+ def self.format(data)
6
+ underscore parse(data)
7
+ end
8
+
9
+ def self.underscore(data)
10
+ if data.is_a? Array
11
+ data.map { |array_value| HashUtil.underscore_keys array_value }
12
+ else
13
+ HashUtil.underscore_keys data
14
+ end
15
+ end
16
+
17
+ def self.parse(data)
18
+ JSON.parse data.content
19
+ end
20
+
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,75 @@
1
+ module Litmus
2
+ module Infrastructure
3
+ class GenericError < StandardError
4
+ include Base
5
+ end
6
+
7
+ # Raised when Litmus::Infrastructure isn't properly configured. See Configuration for
8
+ # details on configuring Litmus::Infrastructure.
9
+ class NotConfigured < GenericError; end
10
+
11
+ # Raised when a GUID cannot be found and a 404 response code is received.
12
+ class NotFound < GenericError
13
+ def initialize(response) #:nodoc:
14
+ headers = response.http_header
15
+ req_method = headers.request_method
16
+ req_uri = headers.request_uri
17
+ super "#{req_method} #{req_uri} could not be found"
18
+ end
19
+ end
20
+
21
+ # Raised when the API returns an unauthorized or forbidden response.
22
+ #
23
+ # === Attributes
24
+ # * <tt>response</tt> - The Response from the Litmus Infrastructure API
25
+ class UnauthorizedResponse < GenericError
26
+ attr_reader :response
27
+
28
+ def initialize(response) #:nodoc:
29
+ @response = response
30
+ message = 'Your username and/or password were invalid. Please check your credentials and try again.'
31
+ # logger.error "[Litmus::Infrastructure] [Response] #{response.inspect}"
32
+ super message
33
+ end
34
+ end
35
+
36
+ # Raised when a 500 response code has been received.
37
+ #
38
+ # === Attributes
39
+ # * <tt>response</tt> - The Response from the Litmus Infrastructure API
40
+ class ServerException < GenericError
41
+ attr_reader :response
42
+
43
+ def initialize(response, params = nil) #:nodoc:
44
+ @response = response
45
+ status = response.status
46
+ headers = response.http_header
47
+ req_method = headers.request_method
48
+ req_uri = headers.request_uri
49
+ error = headers.reason_phrase
50
+
51
+ message = "#{req_method} #{req_uri} failed with #{status} (#{error})"
52
+ message += "\n\nResponse: #{response.body}"
53
+ message += "\n\nRequest body: #{params.to_json}" if params.is_a?(Hash)
54
+ super message
55
+ end
56
+ end
57
+
58
+ # Raised when the response code does not match that of the expected code.
59
+ #
60
+ # === Attributes
61
+ # * <tt>response</tt> - The Response from the Litmus Infrastructure API
62
+ class InvalidResponse < GenericError
63
+ attr_reader :error_messages, :response
64
+
65
+ def initialize(response, expected_status = 200) #:nodoc:
66
+ @error_messages = response.json? ? Array(response.json[:message]) : []
67
+ @response = response
68
+ # logger.error "[Litmus::Infrastructure] [Response] #{response.inspect}"
69
+ message = "Got status code #{response.status}, but expected #{expected_status}." <<
70
+ ' Message: ' << @error_messages.join(', ') if @error_messages.any?
71
+ super message
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,39 @@
1
+ require 'active_support/core_ext/string/inflections'
2
+
3
+ module Litmus
4
+ module Infrastructure #:nodoc:
5
+
6
+ class HashUtil #:nodoc:
7
+ # Returns a new hash with all keys converted to :underscore_symbols from its
8
+ # CamelCase counterpart
9
+ def self.underscore_keys(hash)
10
+ deep_transform_keys(hash) { |key| key.underscore.to_sym }
11
+ end
12
+
13
+ # Returns a new hash with all keys converted to CameCase
14
+ def self.camel_keys(hash)
15
+ deep_transform_keys(hash) { |key| key.to_s.camelcase.to_s }
16
+ end
17
+
18
+ private
19
+
20
+ # Return a new hash with all keys converted by the block operation. This includes the keys from the root hash and from all nested hashes.
21
+ def self.deep_transform_keys(object, &block)
22
+ return object unless object.is_a? Hash
23
+ result = {}
24
+ object.each do |key, value|
25
+ result[yield(key)] =
26
+ if value.is_a?(Hash)
27
+ deep_transform_keys(value, &block)
28
+ elsif value.is_a?(Array)
29
+ value.map { |array_value| deep_transform_keys(array_value, &block) }
30
+ else
31
+ value
32
+ end
33
+ end
34
+ result
35
+ end
36
+ end
37
+
38
+ end
39
+ end
@@ -0,0 +1,110 @@
1
+ require 'base64'
2
+ require 'litmus/infrastructure/base'
3
+
4
+ module Litmus
5
+ module Infrastructure
6
+
7
+ class Model
8
+ include Base
9
+
10
+ # Create a model with attributes provided in <tt>attrs</tt>. Only
11
+ # attributes defined in <tt>attributes</tt> will be allowed.
12
+ def initialize(attrs = {})
13
+ set_attributes(attrs)
14
+ end
15
+
16
+ # Serialize the object to a Hash to send back to the API
17
+ def serialize
18
+ hash = {}
19
+ self.class.safe_attributes.each { |key| hash[key] = self.send(key) }
20
+ HashUtil.camel_keys hash
21
+ end
22
+
23
+ def set_attributes(attrs = {})
24
+ safe_attrs = attrs.select { |key, _| self.class.safe_attributes.include?(key) }
25
+ safe_attrs.each { |key, value| self.send "#{key}=".to_sym, value }
26
+ end
27
+
28
+ def to_hash
29
+ self.class.safe_attributes.inject({}) do |hash, key|
30
+ hash[key] = instance_variable_get("@#{key}")
31
+ hash
32
+ end
33
+ end
34
+
35
+ class << self
36
+
37
+ # Create an array of safe attributes and call <tt>attr_accessor</tt>
38
+ def attributes(*attrs)
39
+ @safe_attributes ||= []
40
+ @safe_attributes.concat attrs
41
+ attr_accessor(*attrs)
42
+ end
43
+
44
+ def safe_attributes
45
+ @safe_attributes || []
46
+ end
47
+
48
+ # Perform an HTTP request
49
+ def request(method = :get, action = nil, params = {}, headers = {}, follow_redirect = false, &block)
50
+ url = "#{config.url}#{action}"
51
+ auth = Base64.strict_encode64("#{config.username}:#{config.password}")
52
+
53
+ # set timeouts
54
+ if config.timeout_connect
55
+ client.connect_timeout = config.timeout_connect.to_i
56
+ end
57
+ if config.timeout_receive
58
+ client.receive_timeout = config.timeout_receive.to_i
59
+ end
60
+
61
+ logger.debug <<-DEBUG.strip
62
+ [Litmus::Infrastructure] #{ method.to_s.upcase } #{ url }
63
+ #{ params.inspect }
64
+ DEBUG
65
+
66
+ request_headers = {
67
+ 'Authorization' => "Basic #{auth}",
68
+ 'Accept' => 'application/json',
69
+ 'Content-Type' => 'application/json'
70
+ }.merge headers
71
+
72
+ response = client.send method, url, params, request_headers, follow_redirect, &block
73
+
74
+ logger.debug "[Litmus::Infrastructure] Response Code: #{response.status}"
75
+
76
+ if response.status == 404
77
+ raise NotFound.new(response)
78
+ elsif response.status >= 401 && response.status <= 403
79
+ raise UnauthorizedResponse.new(response)
80
+ elsif response.status == 400 || (response.status >= 405 && response.status < 600)
81
+ raise ServerException.new(response, params)
82
+ else
83
+ Response.new response
84
+ end
85
+ end
86
+
87
+ # Perform a POST request
88
+ def post(action = nil, params = {})
89
+ request(:post, action, params)
90
+ end
91
+
92
+ # Perform a PUT request
93
+ def put(action = nil, params = {})
94
+ request(:put, action, params)
95
+ end
96
+
97
+ # Perform a GET request
98
+ def get(action = nil, params = {})
99
+ request(:get, action, params)
100
+ end
101
+
102
+ def map_response(response, klass)
103
+ response.json.map { |obj| klass.new obj }
104
+ end
105
+
106
+ end
107
+ end
108
+
109
+ end
110
+ end
@@ -0,0 +1,53 @@
1
+ require 'json'
2
+ require 'litmus/infrastructure/hash_util'
3
+
4
+ module Litmus
5
+ module Infrastructure
6
+
7
+ # A response returned from perform an HTTP action. Response gives you access
8
+ # to the content of the response, status code, and the HTTPClient response.
9
+ #
10
+ # === Attributes
11
+ # * <tt>raw</tt> - The HTTP::Message returned from the request
12
+ # * <tt>content</tt> - String representation of the response body
13
+ # * <tt>status</tt> - HTTP status code
14
+ class Response
15
+ SUCCESS_CODES = (200..299).freeze
16
+ attr_accessor :raw, :content, :status
17
+
18
+ def initialize(response) #:nodoc:
19
+ self.raw = response
20
+ self.content = response.content
21
+ self.status = response.status
22
+ end
23
+
24
+ # Parse <tt>content</tt> as JSON and return the result. All keys will be
25
+ # converted to their underscore and symbol equivalent.
26
+ def json
27
+ return nil if content.empty?
28
+ @json ||= JSON.parse(content)
29
+ if @json.is_a?(Array)
30
+ @json.map { |obj| HashUtil.underscore_keys obj }
31
+ else
32
+ HashUtil.underscore_keys @json
33
+ end
34
+ end
35
+
36
+ # Determine if the response was a JSON result
37
+ #
38
+ # === Returns
39
+ # Boolean - true if the response's Content-Type is "json"
40
+ def json?
41
+ raw.headers['Content-Type'] == 'json'
42
+ end
43
+
44
+ # Determine if the response was successful.
45
+ #
46
+ # === Returns
47
+ # Boolean - true if the response's status is in the 2xx series
48
+ def successful?
49
+ SUCCESS_CODES.include? status
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,5 @@
1
+ module Litmus
2
+ module Infrastructure
3
+ VERSION = "0.2.6"
4
+ end
5
+ end
@@ -0,0 +1,43 @@
1
+ require 'httpclient'
2
+ require 'httpclient/include_client'
3
+
4
+ require 'litmus/infrastructure/version'
5
+ require 'litmus/infrastructure/hash_util'
6
+ require 'litmus/infrastructure/data_formatter'
7
+ require 'litmus/infrastructure/base'
8
+ require 'litmus/infrastructure/response'
9
+ require 'litmus/infrastructure/configuration'
10
+ require 'litmus/infrastructure/exceptions'
11
+ require 'litmus/infrastructure/model'
12
+
13
+ require 'active_support/core_ext/module'
14
+
15
+ module Litmus
16
+ module Infrastructure
17
+ def self.included(base)
18
+ base.extend(ClassMethods)
19
+ base.extend(HTTPClient::IncludeClient)
20
+ base.send(:include_http_client)
21
+ end
22
+
23
+ module ClassMethods
24
+ def configure
25
+ @configuration ||= Configuration.new
26
+ yield @configuration
27
+ end
28
+
29
+ def configuration
30
+ if @configuration.nil?
31
+ raise NotConfigured, "You've not yet configured this service. See documentation for details."
32
+ end
33
+
34
+ @configuration
35
+ end
36
+
37
+ def logger
38
+ configuration.logger
39
+ end
40
+ end
41
+
42
+ end
43
+ end
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'litmus/infrastructure/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'litmus-infrastructure'
8
+ spec.version = Litmus::Infrastructure::VERSION
9
+ spec.authors = ["Kevin Thompson", "Eddie Cianci", "Drew Tempelmeyer"]
10
+ spec.email = ["kevinthompson@litmus.com", "eddie@litmus.com", "drew@litmus.com"]
11
+ spec.summary = %q{A module for interacting with the Litmus infrastructure APIs}
12
+ spec.homepage = ""
13
+
14
+ spec.files = `git ls-files -z`.split("\x0")
15
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
16
+ spec.require_paths = ['lib']
17
+
18
+ spec.add_dependency 'activesupport', '>= 4.0.0', '< 6.0'
19
+ spec.add_dependency 'httpclient', '~> 2.5'
20
+
21
+ spec.add_development_dependency 'rspec'
22
+ spec.add_development_dependency 'rake'
23
+ end
@@ -0,0 +1,24 @@
1
+ require "spec_helper"
2
+
3
+ module Fake1
4
+ include Litmus::Infrastructure
5
+ module Foo1
6
+ class Bar1 < Litmus::Infrastructure::Model
7
+ end
8
+ end
9
+ end
10
+
11
+ module Fake2
12
+ module Foo2
13
+ include Litmus::Infrastructure
14
+ class Bar2 < Litmus::Infrastructure::Model
15
+ end
16
+ end
17
+ end
18
+
19
+ describe Litmus::Infrastructure::Base do
20
+ it "sets the correct namespace" do
21
+ expect(Fake1::Foo1::Bar1.namespace).to eq Fake1
22
+ expect(Fake2::Foo2::Bar2.namespace).to eq Fake2::Foo2
23
+ end
24
+ end
@@ -0,0 +1,74 @@
1
+ require "spec_helper"
2
+
3
+ describe Litmus::Infrastructure::Model do
4
+ let(:client){ double('HTTPClient') }
5
+ let(:logger){ double('Logger') }
6
+ let(:response){ double('Litmus::Infrastructure::Response', status: 200, content: '') }
7
+ let(:config){
8
+ double(
9
+ 'Litmus::Configuration', {
10
+ url: '',
11
+ username: '',
12
+ password: '',
13
+ timeout_connect: 10,
14
+ timeout_receive: 10,
15
+ logger: logger
16
+ }
17
+ )
18
+ }
19
+
20
+ before do
21
+ allow(subject.class).to receive(:client).and_return(client)
22
+ allow(subject.class).to receive(:config).and_return(config)
23
+ allow(client).to receive(:connect_timeout=)
24
+ allow(client).to receive(:receive_timeout=)
25
+ allow(logger).to receive(:debug)
26
+ end
27
+
28
+ context '::attributes' do
29
+ class TestModel < Litmus::Infrastructure::Model
30
+ attributes :test_id
31
+ attr_accessor :name
32
+ end
33
+
34
+ it 'has no @safe_attributes' do
35
+ expect(Litmus::Infrastructure::Model.safe_attributes).to eq([])
36
+ end
37
+
38
+ it 'has :test_id in @safe_attributes' do
39
+ expect(TestModel.safe_attributes).to eq [:test_id]
40
+ end
41
+
42
+ it 'creates writer' do
43
+ expect(TestModel.new).to respond_to 'test_id='.to_sym
44
+ end
45
+
46
+ it 'creates reader' do
47
+ expect(TestModel.new).to respond_to :test_id
48
+ end
49
+
50
+ context '::initialize' do
51
+ it 'only sets what is in @safe_attributes' do
52
+ model = TestModel.new(test_id: 123, name: 'Test')
53
+ expect(model.test_id).to eq 123
54
+ expect(model.name).to be_nil
55
+ end
56
+ end
57
+ end
58
+
59
+ describe '.request' do
60
+ context 'when the request content type is text/csv' do
61
+ let(:auth){ Base64.strict_encode64("#{config.username}:#{config.password}") }
62
+ let(:request_headers){ Hash['Accept' => 'text/csv', 'Content-Type' => 'text/csv'] }
63
+ let(:request_arguments){ [:get, 'Example', {}, request_headers] }
64
+ let(:headers){ Hash['Authorization' => "Basic #{auth}"].merge(request_headers) }
65
+ let(:arguments){ [:get, 'Example', {}, headers, false] }
66
+
67
+ it 'sends the appropriate header when making a request' do
68
+ expect(client).to receive(:send).with(*arguments).and_return(response)
69
+ subject.class.request(*request_arguments)
70
+ end
71
+
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,50 @@
1
+ require 'spec_helper'
2
+ require 'litmus/infrastructure/response'
3
+
4
+ describe Litmus::Infrastructure::Response do
5
+ let(:json_string) { { 'Message' => 'Success.' }.to_json }
6
+ let(:status) { 200 }
7
+ let(:response) do
8
+ Litmus::Infrastructure::Response.new(
9
+ double('HTTP::Message', status: status, content: json_string)
10
+ )
11
+ end
12
+
13
+ describe "#json" do
14
+ it "returns correct data from response" do
15
+ expect(response.json).to eq(message: "Success.")
16
+ end
17
+ end
18
+
19
+ describe "#json when response is empty" do
20
+ let(:json_string) { "" }
21
+
22
+ it "returns nil if no data was passed in response" do
23
+ expect(response.json).to be_nil
24
+ end
25
+ end
26
+
27
+ it '#raw' do
28
+ expect(response.raw.status).to eq 200
29
+ end
30
+
31
+ it '#content' do
32
+ expect(response.content).to eq json_string
33
+ end
34
+
35
+ describe "#successful?" do
36
+ context "when the status code is in the 2xx series" do
37
+ it "returns true" do
38
+ expect(response).to be_successful
39
+ end
40
+ end
41
+
42
+ context "when the status code is outside of the 2xx series" do
43
+ let(:status) { 500 }
44
+
45
+ it "returns false" do
46
+ expect(response).to_not be_successful
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,8 @@
1
+ $LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
2
+ require "litmus/infrastructure"
3
+
4
+ RSpec.configure do |config|
5
+ config.fail_fast = true
6
+ config.color = true
7
+ config.tty = true
8
+ end
metadata ADDED
@@ -0,0 +1,135 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: litmus-infrastructure
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.6
5
+ platform: ruby
6
+ authors:
7
+ - Kevin Thompson
8
+ - Eddie Cianci
9
+ - Drew Tempelmeyer
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2021-11-29 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: activesupport
17
+ requirement: !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - ">="
20
+ - !ruby/object:Gem::Version
21
+ version: 4.0.0
22
+ - - "<"
23
+ - !ruby/object:Gem::Version
24
+ version: '6.0'
25
+ type: :runtime
26
+ prerelease: false
27
+ version_requirements: !ruby/object:Gem::Requirement
28
+ requirements:
29
+ - - ">="
30
+ - !ruby/object:Gem::Version
31
+ version: 4.0.0
32
+ - - "<"
33
+ - !ruby/object:Gem::Version
34
+ version: '6.0'
35
+ - !ruby/object:Gem::Dependency
36
+ name: httpclient
37
+ requirement: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '2.5'
42
+ type: :runtime
43
+ prerelease: false
44
+ version_requirements: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: '2.5'
49
+ - !ruby/object:Gem::Dependency
50
+ name: rspec
51
+ requirement: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ type: :development
57
+ prerelease: false
58
+ version_requirements: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ - !ruby/object:Gem::Dependency
64
+ name: rake
65
+ requirement: !ruby/object:Gem::Requirement
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
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ description:
78
+ email:
79
+ - kevinthompson@litmus.com
80
+ - eddie@litmus.com
81
+ - drew@litmus.com
82
+ executables: []
83
+ extensions: []
84
+ extra_rdoc_files: []
85
+ files:
86
+ - ".gitignore"
87
+ - ".ruby-version"
88
+ - Gemfile
89
+ - LICENSE.txt
90
+ - README.md
91
+ - Rakefile
92
+ - bin/console
93
+ - bin/rake
94
+ - bin/setup
95
+ - lib/litmus/infrastructure.rb
96
+ - lib/litmus/infrastructure/base.rb
97
+ - lib/litmus/infrastructure/configuration.rb
98
+ - lib/litmus/infrastructure/data_formatter.rb
99
+ - lib/litmus/infrastructure/exceptions.rb
100
+ - lib/litmus/infrastructure/hash_util.rb
101
+ - lib/litmus/infrastructure/model.rb
102
+ - lib/litmus/infrastructure/response.rb
103
+ - lib/litmus/infrastructure/version.rb
104
+ - litmus-infrastructure.gemspec
105
+ - spec/lib/litmus/infrastructure/base_spec.rb
106
+ - spec/lib/litmus/infrastructure/model_spec.rb
107
+ - spec/lib/litmus/infrastructure/response_spec.rb
108
+ - spec/spec_helper.rb
109
+ homepage: ''
110
+ licenses: []
111
+ metadata: {}
112
+ post_install_message:
113
+ rdoc_options: []
114
+ require_paths:
115
+ - lib
116
+ required_ruby_version: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ required_rubygems_version: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ requirements: []
127
+ rubygems_version: 3.1.4
128
+ signing_key:
129
+ specification_version: 4
130
+ summary: A module for interacting with the Litmus infrastructure APIs
131
+ test_files:
132
+ - spec/lib/litmus/infrastructure/base_spec.rb
133
+ - spec/lib/litmus/infrastructure/model_spec.rb
134
+ - spec/lib/litmus/infrastructure/response_spec.rb
135
+ - spec/spec_helper.rb