litmus-infrastructure 0.2.6

Sign up to get free protection for your applications and to get access to all the features.
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