diff --git a/Gemfile.lock b/Gemfile.lock
index 6ba659f..f50a52e 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,5 +1,5 @@
GIT
- remote: git://github.com/pivotal/sinclair.git
+ remote: https://github.com/pivotal/sinclair.git
revision: b8c88158d000e75c6b8296a96e2dfe6da82ed823
specs:
sinclair (0.2.0)
@@ -219,7 +219,7 @@ GEM
http_parser.rb (~> 0.6.0)
multi_json
puma (2.16.0)
- rack (1.6.4)
+ rack (1.6.13)
rack-cors (0.4.0)
rack-test (0.6.3)
rack (>= 1.0)
diff --git a/vendor/cache/ffi-1.9.14.gem b/vendor/cache/ffi-1.9.14.gem
new file mode 100644
index 0000000..4d0db22
Binary files /dev/null and b/vendor/cache/ffi-1.9.14.gem differ
diff --git a/vendor/cache/rack-1.6.13.gem b/vendor/cache/rack-1.6.13.gem
new file mode 100644
index 0000000..cea335c
Binary files /dev/null and b/vendor/cache/rack-1.6.13.gem differ
diff --git a/vendor/cache/rack-1.6.4.gem b/vendor/cache/rack-1.6.4.gem
deleted file mode 100644
index 6d06fed..0000000
Binary files a/vendor/cache/rack-1.6.4.gem and /dev/null differ
diff --git a/vendor/cache/rubyzip-1.2.0.gem b/vendor/cache/rubyzip-1.2.0.gem
new file mode 100644
index 0000000..021092a
Binary files /dev/null and b/vendor/cache/rubyzip-1.2.0.gem differ
diff --git a/vendor/cache/selenium-webdriver-2.53.4.gem b/vendor/cache/selenium-webdriver-2.53.4.gem
new file mode 100644
index 0000000..c5620eb
Binary files /dev/null and b/vendor/cache/selenium-webdriver-2.53.4.gem differ
diff --git a/vendor/cache/sinclair-b8c88158d000/.bundlecache b/vendor/cache/sinclair-b8c88158d000/.bundlecache
new file mode 100644
index 0000000..e69de29
diff --git a/vendor/cache/sinclair-b8c88158d000/.gitignore b/vendor/cache/sinclair-b8c88158d000/.gitignore
new file mode 100644
index 0000000..9106b2a
--- /dev/null
+++ b/vendor/cache/sinclair-b8c88158d000/.gitignore
@@ -0,0 +1,8 @@
+/.bundle/
+/.yardoc
+/_yardoc/
+/coverage/
+/doc/
+/pkg/
+/spec/reports/
+/tmp/
diff --git a/vendor/cache/sinclair-b8c88158d000/.rspec b/vendor/cache/sinclair-b8c88158d000/.rspec
new file mode 100644
index 0000000..8c18f1a
--- /dev/null
+++ b/vendor/cache/sinclair-b8c88158d000/.rspec
@@ -0,0 +1,2 @@
+--format documentation
+--color
diff --git a/vendor/cache/sinclair-b8c88158d000/.ruby-version b/vendor/cache/sinclair-b8c88158d000/.ruby-version
new file mode 100644
index 0000000..276cbf9
--- /dev/null
+++ b/vendor/cache/sinclair-b8c88158d000/.ruby-version
@@ -0,0 +1 @@
+2.3.0
diff --git a/vendor/cache/sinclair-b8c88158d000/.travis.yml b/vendor/cache/sinclair-b8c88158d000/.travis.yml
new file mode 100644
index 0000000..eb6b0b7
--- /dev/null
+++ b/vendor/cache/sinclair-b8c88158d000/.travis.yml
@@ -0,0 +1,9 @@
+language: ruby
+rvm:
+ - 2.1.5
+
+before_install: gem install bundler
+
+addons:
+ code_climate:
+ repo_token: 8072f0a2d484fa3f658829f9c44ebbd4c10647800cb3a2fa0f3f7337be585050
diff --git a/vendor/cache/sinclair-b8c88158d000/Gemfile b/vendor/cache/sinclair-b8c88158d000/Gemfile
new file mode 100644
index 0000000..9ee599f
--- /dev/null
+++ b/vendor/cache/sinclair-b8c88158d000/Gemfile
@@ -0,0 +1,4 @@
+source 'https://rubygems.org'
+
+# Specify your gem's dependencies in sinclair.gemspec
+gemspec
diff --git a/vendor/cache/sinclair-b8c88158d000/LICENSE.txt b/vendor/cache/sinclair-b8c88158d000/LICENSE.txt
new file mode 100644
index 0000000..bfb4cf5
--- /dev/null
+++ b/vendor/cache/sinclair-b8c88158d000/LICENSE.txt
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015 TODO: Write your name
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/vendor/cache/sinclair-b8c88158d000/README.md b/vendor/cache/sinclair-b8c88158d000/README.md
new file mode 100644
index 0000000..2728d51
--- /dev/null
+++ b/vendor/cache/sinclair-b8c88158d000/README.md
@@ -0,0 +1,75 @@
+# Sinclair
+
+[](https://travis-ci.org/pivotal/sinclair)
+[](https://codeclimate.com/github/pivotal/sinclair)
+[](https://codeclimate.com/github/pivotal/sinclair/coverage)
+
+
+
+Sinclair is a gem that makes using the OpenAir API tolerable.
+
+## Usage
+
+### Basic Usage
+
+Create the API client using your connection parameters:
+
+```
+client = Sinclair::OpenAirApiClient.new(
+ username: 'Username', password: 'Password', company: 'Company', client: 'Client', key: 'APIKEY'
+)
+```
+
+Create an XML ERB template containing your OpenAir request:
+
+```
+
+
+ <%= name %>
+
+
+
+```
+
+Make the request:
+
+```
+template = File.read('your template file')
+customers = client.send_request(template: template, model: 'Customer', locals: { name: 'Foo' })
+```
+
+Note that `model` should be the type of data returned by the API. In the above example, we are requesting `Customer` data, so the `model` would be `Customer`. The return value includes all of the XML response data that is nested under `model`.
+
+By default, Sinclair will make a `Read` request. To change the type of request, supply a `method` argument:
+
+```
+customers = client.send_request(template: template, model: 'Customer', method: 'Add')
+```
+
+Sinclair will always return an array of items regardless of the number of items returned.
+
+### Pagination
+
+Sinclair will attempt to make additional requests if the number of items returned is equal to the limit supplied in the request. When this happens, Sinclair will add an `offset` parameter to the locals used to render the template. You will need to change your request template to include the `offset`.
+
+```
+
+
+ <%= name %>
+
+
+```
+
+### Debugging
+
+If you want to see the actual requests Sinclair is making, you can supply a logger which Sinclair will use to log both the requests and responses seen from OpenAir:
+
+```
+client.logger = Logger.new(STDOUT)
+client.logger.level = Logger::DEBUG
+```
+
+## License
+
+The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
+
diff --git a/vendor/cache/sinclair-b8c88158d000/Rakefile b/vendor/cache/sinclair-b8c88158d000/Rakefile
new file mode 100644
index 0000000..b7e9ed5
--- /dev/null
+++ b/vendor/cache/sinclair-b8c88158d000/Rakefile
@@ -0,0 +1,6 @@
+require "bundler/gem_tasks"
+require "rspec/core/rake_task"
+
+RSpec::Core::RakeTask.new(:spec)
+
+task :default => :spec
diff --git a/vendor/cache/sinclair-b8c88158d000/bin/console b/vendor/cache/sinclair-b8c88158d000/bin/console
new file mode 100755
index 0000000..96c5852
--- /dev/null
+++ b/vendor/cache/sinclair-b8c88158d000/bin/console
@@ -0,0 +1,14 @@
+#!/usr/bin/env ruby
+
+require "bundler/setup"
+require "sinclair"
+
+# You can add fixtures and/or initialization code here to make experimenting
+# with your gem easier. You can also use a different console, if you like.
+
+# (If you use this, don't forget to add pry to your Gemfile!)
+# require "pry"
+# Pry.start
+
+require "irb"
+IRB.start
diff --git a/vendor/cache/sinclair-b8c88158d000/bin/setup b/vendor/cache/sinclair-b8c88158d000/bin/setup
new file mode 100755
index 0000000..b65ed50
--- /dev/null
+++ b/vendor/cache/sinclair-b8c88158d000/bin/setup
@@ -0,0 +1,7 @@
+#!/bin/bash
+set -euo pipefail
+IFS=$'\n\t'
+
+bundle install
+
+# Do any other automated setup that you need to do here
diff --git a/vendor/cache/sinclair-b8c88158d000/lib/sinclair.rb b/vendor/cache/sinclair-b8c88158d000/lib/sinclair.rb
new file mode 100644
index 0000000..dd2535b
--- /dev/null
+++ b/vendor/cache/sinclair-b8c88158d000/lib/sinclair.rb
@@ -0,0 +1,12 @@
+require 'sinclair/version'
+require 'sinclair/request'
+require 'sinclair/open_air_api_client'
+require 'sinclair/errors/open_air_authentication_failure'
+require 'sinclair/errors/open_air_response_error'
+require 'sinclair/errors/open_air_invalid_data'
+require 'sinclair/errors/open_air_response_timeout'
+require 'sinclair/errors/open_air_response_unrecognized'
+require 'sinclair/errors/open_air_user_locked'
+
+module Sinclair
+end
diff --git a/vendor/cache/sinclair-b8c88158d000/lib/sinclair/errors/open_air_authentication_failure.rb b/vendor/cache/sinclair-b8c88158d000/lib/sinclair/errors/open_air_authentication_failure.rb
new file mode 100644
index 0000000..7535f71
--- /dev/null
+++ b/vendor/cache/sinclair-b8c88158d000/lib/sinclair/errors/open_air_authentication_failure.rb
@@ -0,0 +1,4 @@
+module Sinclair
+ class OpenAirAuthenticationFailure < StandardError
+ end
+end
diff --git a/vendor/cache/sinclair-b8c88158d000/lib/sinclair/errors/open_air_invalid_data.rb b/vendor/cache/sinclair-b8c88158d000/lib/sinclair/errors/open_air_invalid_data.rb
new file mode 100644
index 0000000..3eaebce
--- /dev/null
+++ b/vendor/cache/sinclair-b8c88158d000/lib/sinclair/errors/open_air_invalid_data.rb
@@ -0,0 +1,13 @@
+module Sinclair
+ class OpenAirInvalidData < StandardError
+ attr_reader :errors
+
+ def initialize(errors)
+ @errors = errors
+ end
+
+ def message
+ errors.join(', ')
+ end
+ end
+end
diff --git a/vendor/cache/sinclair-b8c88158d000/lib/sinclair/errors/open_air_response_error.rb b/vendor/cache/sinclair-b8c88158d000/lib/sinclair/errors/open_air_response_error.rb
new file mode 100644
index 0000000..d791693
--- /dev/null
+++ b/vendor/cache/sinclair-b8c88158d000/lib/sinclair/errors/open_air_response_error.rb
@@ -0,0 +1,13 @@
+module Sinclair
+ class OpenAirResponseError < StandardError
+ attr_reader :status
+
+ def initialize(status)
+ @status = status
+ end
+
+ def message
+ "Error making OpenAir request. Got status #{@status}."
+ end
+ end
+end
diff --git a/vendor/cache/sinclair-b8c88158d000/lib/sinclair/errors/open_air_response_timeout.rb b/vendor/cache/sinclair-b8c88158d000/lib/sinclair/errors/open_air_response_timeout.rb
new file mode 100644
index 0000000..6600d6f
--- /dev/null
+++ b/vendor/cache/sinclair-b8c88158d000/lib/sinclair/errors/open_air_response_timeout.rb
@@ -0,0 +1,4 @@
+module Sinclair
+ class OpenAirResponseTimeout < StandardError
+ end
+end
diff --git a/vendor/cache/sinclair-b8c88158d000/lib/sinclair/errors/open_air_response_unrecognized.rb b/vendor/cache/sinclair-b8c88158d000/lib/sinclair/errors/open_air_response_unrecognized.rb
new file mode 100644
index 0000000..4ec8392
--- /dev/null
+++ b/vendor/cache/sinclair-b8c88158d000/lib/sinclair/errors/open_air_response_unrecognized.rb
@@ -0,0 +1,13 @@
+module Sinclair
+ class OpenAirResponseUnrecognized < StandardError
+ attr_reader :response
+
+ def initialize(response)
+ @response = response
+ end
+
+ def message
+ "Unknown OpenAir response: #{response}"
+ end
+ end
+end
diff --git a/vendor/cache/sinclair-b8c88158d000/lib/sinclair/errors/open_air_user_locked.rb b/vendor/cache/sinclair-b8c88158d000/lib/sinclair/errors/open_air_user_locked.rb
new file mode 100644
index 0000000..969ef9d
--- /dev/null
+++ b/vendor/cache/sinclair-b8c88158d000/lib/sinclair/errors/open_air_user_locked.rb
@@ -0,0 +1,4 @@
+module Sinclair
+ class OpenAirUserLocked < StandardError
+ end
+end
diff --git a/vendor/cache/sinclair-b8c88158d000/lib/sinclair/open_air_api_client.rb b/vendor/cache/sinclair-b8c88158d000/lib/sinclair/open_air_api_client.rb
new file mode 100644
index 0000000..4402517
--- /dev/null
+++ b/vendor/cache/sinclair-b8c88158d000/lib/sinclair/open_air_api_client.rb
@@ -0,0 +1,134 @@
+require 'nori'
+require 'faraday'
+require 'nokogiri'
+
+module Sinclair
+ class OpenAirApiClient
+ attr_accessor :logger, :last_request, :last_response
+
+ def initialize(username:, password:, company:, client:, key:, url: 'https://www.openair.com', limit: '1000', timeout: 180, open_timeout: 120)
+ @username = username
+ @password = password
+ @company = company
+ @client = client
+ @key = key
+ @url = url
+ @limit = limit
+ @timeout = timeout
+ @open_timeout = open_timeout
+ end
+
+ def send_request(template: , model: , method: 'Read', locals: {})
+ response = {}
+ response[model] = []
+
+ while true
+ page = process_page(template: template, method: method, model: model, locals: {offset: response[model].length}.merge(locals))
+ break unless page[model]
+ returned_models = page.keys
+ returned_models.each do |m|
+ response[m] ? response[m] += page[m] : response[m] = page[m]
+ end
+ break if page[model].length < @limit.to_i
+ end
+ response
+ end
+
+ private
+
+ def process_page(template:, method:, model:, locals: {})
+ response = make_request(locals, template)
+
+ log_request unless logger.nil?
+
+ check_auth_status(response)
+
+ read = response['response'][method]
+ read = [read] unless read.is_a?(Array)
+
+ check_response_status(read, model)
+ map_response_by_model(read)
+ end
+
+ def make_request(locals, template)
+ response = get_response(template, locals)
+ self.last_response = response.body
+ Nori.new(advanced_typecasting: false).parse(response.body)
+ end
+
+ def invalid_read_status(status)
+ status != 0 && status != 601
+ end
+
+ def map_response_by_model(response)
+ result = {}
+ returned_models = find_returned_models(response)
+ returned_models.each { |m| result[m] = [] }
+
+ response.each do |r|
+ model = returned_models.find{|m| r.keys.include?(m)}
+ result[model] << r[model]
+ end
+
+ result.map do |model, items|
+ result[model] = items.flatten.compact
+ end
+
+ result
+ end
+
+ def find_returned_models(response)
+ response.map do |r|
+ r.keys[0]
+ end.compact.uniq
+ end
+
+ def check_auth_status(response)
+ raise Sinclair::OpenAirResponseUnrecognized.new(response) if response['response']['Auth'].nil?
+
+ auth_status = response['response']['Auth']['@status'].to_i
+ raise Sinclair::OpenAirUserLocked if auth_status == 416
+ raise Sinclair::OpenAirAuthenticationFailure if auth_status != 0
+ end
+
+ def check_response_status(read, model)
+ statuses = read.map { |r| r['@status'].to_i }
+ if statuses.any? { |s| s == 1002 }
+ errors = read.select{|r| r['@status'].to_i == 1002}.map{|r| r[model]['errors']}
+ raise Sinclair::OpenAirInvalidData.new(errors)
+ elsif statuses.any? { |s| invalid_read_status(s) }
+ raise Sinclair::OpenAirResponseError.new(statuses.find { |s| invalid_read_status(s) })
+ end
+ end
+
+ def get_response(template, locals = {})
+ options = {request: {timeout: @timeout, open_timeout: @open_timeout}}
+ begin
+ locals = locals.merge(username: @username, password: @password, company: @company, client: @client, key: @key, limit: @limit)
+ Faraday.new(@url, options).post('/api.pl') do |request|
+ request.body = Sinclair::Request.new(template).render(locals)
+ request.headers.merge!({'Accept-Encoding' => 'identity'})
+ self.last_request = request.body
+ end
+ rescue Faraday::TimeoutError
+ raise Sinclair::OpenAirResponseTimeout
+ end
+ end
+
+ def log_request
+ logger.debug('#' * 80)
+ logger.debug('# REQUEST')
+ logger.debug('#' * 80)
+ logger.debug(last_request)
+
+ logger.debug('#' * 80)
+ logger.debug('# RESPONSE')
+ logger.debug('#' * 80)
+ logger.debug(last_response)
+ end
+
+ def wrap_response(response)
+ response.is_a?(Array) ? response : [response]
+ end
+ end
+end
diff --git a/vendor/cache/sinclair-b8c88158d000/lib/sinclair/request.rb b/vendor/cache/sinclair-b8c88158d000/lib/sinclair/request.rb
new file mode 100644
index 0000000..d7928b7
--- /dev/null
+++ b/vendor/cache/sinclair-b8c88158d000/lib/sinclair/request.rb
@@ -0,0 +1,24 @@
+require 'erb'
+require 'ostruct'
+
+module Sinclair
+ class Request
+ def initialize(body)
+ @body = body
+ @header = File.read(File.expand_path('../templates/request_header.xml.erb', __FILE__))
+ end
+
+ def render(locals)
+ templates = [@body, @header]
+ templates.inject(nil) do |prev, temp|
+ _render(temp, locals) { prev }
+ end
+ end
+
+ private
+
+ def _render(temp, locals)
+ ERB.new(temp).result(OpenStruct.new(locals).instance_eval { binding }).strip
+ end
+ end
+end
diff --git a/vendor/cache/sinclair-b8c88158d000/lib/sinclair/templates/request_header.xml.erb b/vendor/cache/sinclair-b8c88158d000/lib/sinclair/templates/request_header.xml.erb
new file mode 100644
index 0000000..030dcf3
--- /dev/null
+++ b/vendor/cache/sinclair-b8c88158d000/lib/sinclair/templates/request_header.xml.erb
@@ -0,0 +1,11 @@
+
+
+
+
+ <%= company %>
+ <%= username %>
+ <%= password %>
+
+
+ <%= yield %>
+
diff --git a/vendor/cache/sinclair-b8c88158d000/lib/sinclair/version.rb b/vendor/cache/sinclair-b8c88158d000/lib/sinclair/version.rb
new file mode 100644
index 0000000..6bcf2c9
--- /dev/null
+++ b/vendor/cache/sinclair-b8c88158d000/lib/sinclair/version.rb
@@ -0,0 +1,3 @@
+module Sinclair
+ VERSION = '0.2.0'
+end
diff --git a/vendor/cache/sinclair-b8c88158d000/sinclair.gemspec b/vendor/cache/sinclair-b8c88158d000/sinclair.gemspec
new file mode 100644
index 0000000..affb530
--- /dev/null
+++ b/vendor/cache/sinclair-b8c88158d000/sinclair.gemspec
@@ -0,0 +1,46 @@
+# -*- encoding: utf-8 -*-
+# stub: sinclair 0.2.0 ruby lib
+
+Gem::Specification.new do |s|
+ s.name = "sinclair".freeze
+ s.version = "0.2.0"
+
+ s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
+ s.require_paths = ["lib".freeze]
+ s.authors = ["Pivotal IAD".freeze]
+ s.bindir = "exe".freeze
+ s.date = "2024-02-29"
+ s.description = "Sinclair is a gem that makes using the OpenAir API tolerable.".freeze
+ s.email = ["iad-dev@pivotal.io".freeze]
+ s.files = [".gitignore".freeze, ".rspec".freeze, ".ruby-version".freeze, ".travis.yml".freeze, "Gemfile".freeze, "LICENSE.txt".freeze, "README.md".freeze, "Rakefile".freeze, "bin/console".freeze, "bin/setup".freeze, "lib/sinclair.rb".freeze, "lib/sinclair/errors/open_air_authentication_failure.rb".freeze, "lib/sinclair/errors/open_air_invalid_data.rb".freeze, "lib/sinclair/errors/open_air_response_error.rb".freeze, "lib/sinclair/errors/open_air_response_timeout.rb".freeze, "lib/sinclair/errors/open_air_response_unrecognized.rb".freeze, "lib/sinclair/errors/open_air_user_locked.rb".freeze, "lib/sinclair/open_air_api_client.rb".freeze, "lib/sinclair/request.rb".freeze, "lib/sinclair/templates/request_header.xml.erb".freeze, "lib/sinclair/version.rb".freeze, "sinclair.gemspec".freeze]
+ s.homepage = "http://github.com/pivotal/sinclair".freeze
+ s.licenses = ["MIT".freeze]
+ s.rubygems_version = "3.3.26".freeze
+ s.summary = "Sinclair is a gem that makes using the OpenAir API tolerable.".freeze
+
+ s.installed_by_version = "3.3.26" if s.respond_to? :installed_by_version
+
+ if s.respond_to? :specification_version then
+ s.specification_version = 4
+ end
+
+ if s.respond_to? :add_runtime_dependency then
+ s.add_runtime_dependency(%q.freeze, ["~> 2.6.0"])
+ s.add_runtime_dependency(%q.freeze, ["~> 0.9.0"])
+ s.add_runtime_dependency(%q.freeze, ["~> 1.6.0"])
+ s.add_development_dependency(%q.freeze, ["~> 1.10"])
+ s.add_development_dependency(%q.freeze, ["~> 10.0"])
+ s.add_development_dependency(%q.freeze, [">= 0"])
+ s.add_development_dependency(%q.freeze, [">= 0"])
+ s.add_development_dependency(%q.freeze, [">= 0"])
+ else
+ s.add_dependency(%q.freeze, ["~> 2.6.0"])
+ s.add_dependency(%q.freeze, ["~> 0.9.0"])
+ s.add_dependency(%q.freeze, ["~> 1.6.0"])
+ s.add_dependency(%q.freeze, ["~> 1.10"])
+ s.add_dependency(%q.freeze, ["~> 10.0"])
+ s.add_dependency(%q.freeze, [">= 0"])
+ s.add_dependency(%q.freeze, [">= 0"])
+ s.add_dependency(%q.freeze, [">= 0"])
+ end
+end
diff --git a/vendor/cache/sinclair-b8c88158d000/spec/fixtures/add_request.xml b/vendor/cache/sinclair-b8c88158d000/spec/fixtures/add_request.xml
new file mode 100644
index 0000000..4b75837
--- /dev/null
+++ b/vendor/cache/sinclair-b8c88158d000/spec/fixtures/add_request.xml
@@ -0,0 +1,35 @@
+
+
+
+
+ Company
+ Username
+ Password
+
+
+
+
+ 1234
+
+
+
+
+
+ 9
+ 28
+ 2015
+
+
+
+
+
+
+
+ 10
+ 2
+ 2015
+
+
+
+
+
diff --git a/vendor/cache/sinclair-b8c88158d000/spec/fixtures/add_response.xml b/vendor/cache/sinclair-b8c88158d000/spec/fixtures/add_response.xml
new file mode 100644
index 0000000..dc48b4d
--- /dev/null
+++ b/vendor/cache/sinclair-b8c88158d000/spec/fixtures/add_response.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+ O
+ 1234
+
+ 6375
+
+
+
+
+
+ 12
+ 01
+ 2013
+
+
+
+
+
+
+
+ 11
+ 25
+ 2013
+
+
+
+
+
diff --git a/vendor/cache/sinclair-b8c88158d000/spec/fixtures/error_1002.xml b/vendor/cache/sinclair-b8c88158d000/spec/fixtures/error_1002.xml
new file mode 100644
index 0000000..78bada8
--- /dev/null
+++ b/vendor/cache/sinclair-b8c88158d000/spec/fixtures/error_1002.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+ 1111
+ Submit failed
+
+ The timesheet is terrible
+
+
+
+
+ 1111
+ Submit failed
+
+
+
+
+
+ 1111
+ Submit failed
+
+ The timesheet is really bad
+
+
+
diff --git a/vendor/cache/sinclair-b8c88158d000/spec/fixtures/error_123.xml b/vendor/cache/sinclair-b8c88158d000/spec/fixtures/error_123.xml
new file mode 100644
index 0000000..5996385
--- /dev/null
+++ b/vendor/cache/sinclair-b8c88158d000/spec/fixtures/error_123.xml
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/vendor/cache/sinclair-b8c88158d000/spec/fixtures/error_416.xml b/vendor/cache/sinclair-b8c88158d000/spec/fixtures/error_416.xml
new file mode 100644
index 0000000..d15e93d
--- /dev/null
+++ b/vendor/cache/sinclair-b8c88158d000/spec/fixtures/error_416.xml
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/vendor/cache/sinclair-b8c88158d000/spec/fixtures/error_601.xml b/vendor/cache/sinclair-b8c88158d000/spec/fixtures/error_601.xml
new file mode 100644
index 0000000..b0949bd
--- /dev/null
+++ b/vendor/cache/sinclair-b8c88158d000/spec/fixtures/error_601.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/vendor/cache/sinclair-b8c88158d000/spec/fixtures/error_602.xml b/vendor/cache/sinclair-b8c88158d000/spec/fixtures/error_602.xml
new file mode 100644
index 0000000..03c4268
--- /dev/null
+++ b/vendor/cache/sinclair-b8c88158d000/spec/fixtures/error_602.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/vendor/cache/sinclair-b8c88158d000/spec/fixtures/error_no_auth_status.xml b/vendor/cache/sinclair-b8c88158d000/spec/fixtures/error_no_auth_status.xml
new file mode 100644
index 0000000..2ce045d
--- /dev/null
+++ b/vendor/cache/sinclair-b8c88158d000/spec/fixtures/error_no_auth_status.xml
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/vendor/cache/sinclair-b8c88158d000/spec/fixtures/multiple_commands_request.xml b/vendor/cache/sinclair-b8c88158d000/spec/fixtures/multiple_commands_request.xml
new file mode 100644
index 0000000..d5fe5ce
--- /dev/null
+++ b/vendor/cache/sinclair-b8c88158d000/spec/fixtures/multiple_commands_request.xml
@@ -0,0 +1,20 @@
+
+
+
+
+ Company
+ Username
+ Password
+
+
+
+
+ 1
+
+
+
+
+ 2
+
+
+
diff --git a/vendor/cache/sinclair-b8c88158d000/spec/fixtures/multiple_commands_response.xml b/vendor/cache/sinclair-b8c88158d000/spec/fixtures/multiple_commands_response.xml
new file mode 100644
index 0000000..2da87a9
--- /dev/null
+++ b/vendor/cache/sinclair-b8c88158d000/spec/fixtures/multiple_commands_response.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+ 1
+ Customer 1
+
+
+
+
+ 2
+ Customer 2
+
+
+
diff --git a/vendor/cache/sinclair-b8c88158d000/spec/fixtures/read_multiple_model_response.xml b/vendor/cache/sinclair-b8c88158d000/spec/fixtures/read_multiple_model_response.xml
new file mode 100644
index 0000000..eba4515
--- /dev/null
+++ b/vendor/cache/sinclair-b8c88158d000/spec/fixtures/read_multiple_model_response.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+ fail
+
+
+ success?
+
+
+ unknown
+
+
+
+
+ 123
+
+
+
diff --git a/vendor/cache/sinclair-b8c88158d000/spec/fixtures/read_multiple_request_1.xml b/vendor/cache/sinclair-b8c88158d000/spec/fixtures/read_multiple_request_1.xml
new file mode 100644
index 0000000..03e347d
--- /dev/null
+++ b/vendor/cache/sinclair-b8c88158d000/spec/fixtures/read_multiple_request_1.xml
@@ -0,0 +1,12 @@
+
+
+
+
+ Company
+ Username
+ Password
+
+
+
+
+
diff --git a/vendor/cache/sinclair-b8c88158d000/spec/fixtures/read_multiple_request_2.xml b/vendor/cache/sinclair-b8c88158d000/spec/fixtures/read_multiple_request_2.xml
new file mode 100644
index 0000000..3a5dfd6
--- /dev/null
+++ b/vendor/cache/sinclair-b8c88158d000/spec/fixtures/read_multiple_request_2.xml
@@ -0,0 +1,12 @@
+
+
+
+
+ Company
+ Username
+ Password
+
+
+
+
+
diff --git a/vendor/cache/sinclair-b8c88158d000/spec/fixtures/read_multiple_response_1.xml b/vendor/cache/sinclair-b8c88158d000/spec/fixtures/read_multiple_response_1.xml
new file mode 100644
index 0000000..32e7a36
--- /dev/null
+++ b/vendor/cache/sinclair-b8c88158d000/spec/fixtures/read_multiple_response_1.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+ 1
+ Client 1
+
+
+ 4
+ Client 2
+
+
+ 5
+ Client 3
+
+
+ 6
+ Client 4
+
+
+ 7
+ Client 5
+
+
+
diff --git a/vendor/cache/sinclair-b8c88158d000/spec/fixtures/read_multiple_response_2.xml b/vendor/cache/sinclair-b8c88158d000/spec/fixtures/read_multiple_response_2.xml
new file mode 100644
index 0000000..b412a44
--- /dev/null
+++ b/vendor/cache/sinclair-b8c88158d000/spec/fixtures/read_multiple_response_2.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+ 10
+ Fancy Client
+
+
+ 40
+ Blah Client
+
+
+
diff --git a/vendor/cache/sinclair-b8c88158d000/spec/fixtures/read_single_request.xml b/vendor/cache/sinclair-b8c88158d000/spec/fixtures/read_single_request.xml
new file mode 100644
index 0000000..03e347d
--- /dev/null
+++ b/vendor/cache/sinclair-b8c88158d000/spec/fixtures/read_single_request.xml
@@ -0,0 +1,12 @@
+
+
+
+
+ Company
+ Username
+ Password
+
+
+
+
+
diff --git a/vendor/cache/sinclair-b8c88158d000/spec/fixtures/read_single_response.xml b/vendor/cache/sinclair-b8c88158d000/spec/fixtures/read_single_response.xml
new file mode 100644
index 0000000..fd6a8a7
--- /dev/null
+++ b/vendor/cache/sinclair-b8c88158d000/spec/fixtures/read_single_response.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+ 1
+ Client 1
+
+
+
diff --git a/vendor/cache/sinclair-b8c88158d000/spec/open_air_api_client_spec.rb b/vendor/cache/sinclair-b8c88158d000/spec/open_air_api_client_spec.rb
new file mode 100644
index 0000000..77f5225
--- /dev/null
+++ b/vendor/cache/sinclair-b8c88158d000/spec/open_air_api_client_spec.rb
@@ -0,0 +1,206 @@
+require 'spec_helper'
+
+describe Sinclair::OpenAirApiClient do
+ subject { Sinclair::OpenAirApiClient.new(username: 'Username', password: 'Password', company: 'Company', client: 'Client', key: 'APIKEY', limit: '5') }
+ let(:template) { IO.read("#{ File.expand_path('../templates', __FILE__) }/#{ template_name }") }
+
+ describe '#send_request' do
+ let!(:template_name) { 'single_command.xml.erb' }
+
+ it 'saves the last request and response' do
+ stub_xml_request(
+ request: 'read_single_request',
+ response: 'read_single_response'
+ )
+
+ subject.send_request(template: template, model: 'Customer')
+ expect(subject.last_request).not_to be_nil
+ expect(subject.last_response).not_to be_nil
+ end
+
+ context 'when reading multiple models in a single response' do
+ let!(:template_name) { 'single_command.xml.erb' }
+
+ before do
+ stub_xml_request(
+ request: 'read_single_request',
+ response: 'read_multiple_model_response'
+ )
+ end
+
+ it 'returns a hash with a key for each model type' do
+ response = subject.send_request(template: template, model: 'Thing1')
+ expect(response.keys).to match_array(['Thing1', 'Thing2'])
+ end
+
+ end
+
+ context 'when the response is empty' do
+ let!(:template_name) { 'single_command.xml.erb' }
+
+ before do
+ stub_xml_request(
+ request: 'read_single_request',
+ response: 'error_601'
+ )
+ end
+
+ it 'returns an empty array' do
+ response = subject.send_request(template: template, model: 'Customer')
+ expect(response['Customer']).to be_empty
+ end
+ end
+
+ context 'when the request contains one command' do
+ let!(:template_name) { 'single_command.xml.erb' }
+
+ context 'when the response contains one item' do
+ before do
+ stub_xml_request(
+ request: 'read_single_request',
+ response: 'read_single_response'
+ )
+ end
+
+ it 'returns an array of one item' do
+ response = subject.send_request(template: template, model: 'Customer')
+ expect(response['Customer'].map { |client| client['name'] }).to match_array(['Client 1'])
+ end
+ end
+
+ context 'when the response contains multiple items' do
+ before do
+ stub_xml_request(
+ request: 'read_multiple_request_1',
+ response: 'read_multiple_response_1'
+ )
+
+ stub_xml_request(
+ request: 'read_multiple_request_2',
+ response: 'read_multiple_response_2'
+ )
+ end
+
+ it 'makes multiple requests when the number of responses is greater than the limit' do
+ response = subject.send_request(template: template, model: 'Customer')
+ names = response['Customer'].map { |client| client['name'] }
+
+ expect(names).to match_array(['Blah Client', 'Client 1', 'Client 2', 'Client 3', 'Client 4', 'Client 5', 'Fancy Client'])
+ end
+ end
+ end
+
+ context 'when the request contains multiple commands' do
+ let!(:template_name) { 'multiple_commands.xml.erb' }
+
+ before do
+ stub_xml_request(
+ request: 'multiple_commands_request',
+ response: 'multiple_commands_response'
+ )
+ end
+
+ it 'returns an array of all items' do
+ response = subject.send_request(template: template, model: 'Customer', locals: {customer_ids: [1, 2]})
+ expect(response['Customer'].map { |client| client['name'] }).to match_array(['Customer 1', 'Customer 2'])
+ end
+ end
+
+ context 'when an error occurs' do
+ let!(:template_name) { 'single_command.xml.erb' }
+
+ it 'raises a OpenAirResponseUnrecognized error when the response is malformed' do
+ stub_xml_request(
+ request: 'read_single_request',
+ response: 'error_no_auth_status'
+ )
+
+ expect {
+ subject.send_request(template: template, model: 'Client')
+ }.to raise_error(Sinclair::OpenAirResponseUnrecognized)
+ end
+
+ it 'raises a OpenAirUserLocked error when the response status is 416' do
+ stub_xml_request(
+ request: 'read_single_request',
+ response: 'error_416'
+ )
+
+ expect {
+ subject.send_request(template: template, model: 'Client')
+ }.to raise_error(Sinclair::OpenAirUserLocked)
+ end
+
+ it 'raises a OpenAirAuthenticationFailure error when the response status not zero' do
+ stub_xml_request(
+ request: 'read_single_request',
+ response: 'error_123'
+ )
+
+ expect {
+ subject.send_request(template: template, model: 'Client')
+ }.to raise_error(Sinclair::OpenAirAuthenticationFailure)
+ end
+
+ it 'raises a OpenAirResponseTimeout error when OpenAir times out' do
+ allow_any_instance_of(Faraday::Connection).to receive(:post).and_raise(Faraday::TimeoutError)
+
+ expect {
+ subject.send_request(template: template, model: 'Client')
+ }.to raise_error(Sinclair::OpenAirResponseTimeout)
+ end
+
+ it 'raises a OpenAirResponseError when the read status is not zero' do
+ stub_xml_request(
+ request: 'read_single_request',
+ response: 'error_602'
+ )
+
+ begin
+ subject.send_request(template: template, model: 'Client')
+ rescue Sinclair::OpenAirResponseError => e
+ expect(e.status).to eq(602)
+ expect(e.message).to eq('Error making OpenAir request. Got status 602.')
+ end
+ end
+
+ it 'does not raise an error when the read status is 601' do
+ stub_xml_request(
+ request: 'read_single_request',
+ response: 'error_601'
+ )
+
+ expect {
+ subject.send_request(template: template, model: 'Client')
+ }.not_to raise_error
+ end
+
+ it 'raises an OpenAirInvalidData error when the response status is 1002' do
+ stub_xml_request(
+ request: 'read_single_request',
+ response: 'error_1002'
+ )
+
+ expect {
+ subject.send_request(template: template, model: 'Timesheet', method: 'Submit')
+ }.to raise_error(Sinclair::OpenAirInvalidData, 'The timesheet is terrible, The timesheet is really bad')
+ end
+ end
+
+ context 'when the request is an "add" request' do
+ let!(:template_name) { 'add_command.xml.erb' }
+
+ before do
+ stub_xml_request(
+ request: 'add_request',
+ response: 'add_response'
+ )
+ end
+
+ it 'creates a timesheet' do
+ response = subject.send_request(template: template, model: 'Timesheet', method: 'Add', locals: {start_date: Date.new(2015, 9, 28), end_date: Date.new(2015, 10, 2), user_id: '1234'})
+ expect(response['Timesheet'].map { |timesheet| timesheet['userid'] }).to eq(['1234'])
+ end
+ end
+ end
+end
diff --git a/vendor/cache/sinclair-b8c88158d000/spec/open_air_api_errors_spec.rb b/vendor/cache/sinclair-b8c88158d000/spec/open_air_api_errors_spec.rb
new file mode 100644
index 0000000..f1bdc86
--- /dev/null
+++ b/vendor/cache/sinclair-b8c88158d000/spec/open_air_api_errors_spec.rb
@@ -0,0 +1,10 @@
+require 'spec_helper'
+
+describe 'OpenAir Exceptions' do
+ describe Sinclair::OpenAirResponseError do
+ it 'includes a status code' do
+ e = Sinclair::OpenAirResponseError.new(1003)
+ expect(e.status).to eq(1003)
+ end
+ end
+end
diff --git a/vendor/cache/sinclair-b8c88158d000/spec/request_spec.rb b/vendor/cache/sinclair-b8c88158d000/spec/request_spec.rb
new file mode 100644
index 0000000..6f2c417
--- /dev/null
+++ b/vendor/cache/sinclair-b8c88158d000/spec/request_spec.rb
@@ -0,0 +1,17 @@
+require 'spec_helper'
+
+describe Sinclair::Request do
+ subject { Sinclair::Request.new('<%= foo %>') }
+
+ describe '#render' do
+ let(:output) { ignore_whitespace(subject.render(foo: 'Sinclair')) }
+
+ it 'renders the request header' do
+ expect(output).to include(ignore_whitespace(''))
+ end
+
+ it 'renders the request body' do
+ expect(output).to include(ignore_whitespace('Sinclair'))
+ end
+ end
+end
diff --git a/vendor/cache/sinclair-b8c88158d000/spec/sinclair_spec.rb b/vendor/cache/sinclair-b8c88158d000/spec/sinclair_spec.rb
new file mode 100644
index 0000000..b35d21f
--- /dev/null
+++ b/vendor/cache/sinclair-b8c88158d000/spec/sinclair_spec.rb
@@ -0,0 +1,7 @@
+require 'spec_helper'
+
+describe Sinclair do
+ it 'has a version number' do
+ expect(Sinclair::VERSION).not_to be nil
+ end
+end
diff --git a/vendor/cache/sinclair-b8c88158d000/spec/spec_helper.rb b/vendor/cache/sinclair-b8c88158d000/spec/spec_helper.rb
new file mode 100644
index 0000000..1ca4638
--- /dev/null
+++ b/vendor/cache/sinclair-b8c88158d000/spec/spec_helper.rb
@@ -0,0 +1,27 @@
+$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
+
+require 'codeclimate-test-reporter'
+CodeClimate::TestReporter.start
+
+require 'sinclair'
+require 'webmock'
+
+WebMock.disable_net_connect!(allow_localhost: true, allow: 'codeclimate.com')
+WebMock.enable!
+
+def ignore_whitespace(str)
+ str.gsub(/\s/, '')
+end
+
+def xml_fixture_for(file)
+ File.read(File.join('spec', 'fixtures', "#{file}.xml"))
+end
+
+def stub_xml_request(options = {})
+ request = ignore_whitespace(xml_fixture_for(options[:request]))
+ response = xml_fixture_for(options[:response])
+
+ WebMock.stub_request(:post, 'https://www.openair.com/api.pl').with do |r|
+ ignore_whitespace(r.body) == request
+ end.to_return(status: 200, body: response)
+end
diff --git a/vendor/cache/sinclair-b8c88158d000/spec/templates/add_command.xml.erb b/vendor/cache/sinclair-b8c88158d000/spec/templates/add_command.xml.erb
new file mode 100644
index 0000000..11c567c
--- /dev/null
+++ b/vendor/cache/sinclair-b8c88158d000/spec/templates/add_command.xml.erb
@@ -0,0 +1,25 @@
+
+
+ <%= user_id %>
+
+
+
+
+
+ <%= start_date.month %>
+ <%= start_date.day %>
+ <%= start_date.year %>
+
+
+
+
+
+
+
+ <%= end_date.month %>
+ <%= end_date.day %>
+ <%= end_date.year %>
+
+
+
+
diff --git a/vendor/cache/sinclair-b8c88158d000/spec/templates/multiple_commands.xml.erb b/vendor/cache/sinclair-b8c88158d000/spec/templates/multiple_commands.xml.erb
new file mode 100644
index 0000000..c38c5e3
--- /dev/null
+++ b/vendor/cache/sinclair-b8c88158d000/spec/templates/multiple_commands.xml.erb
@@ -0,0 +1,7 @@
+<% customer_ids.each do |customer_id| %>
+
+
+ <%= customer_id %>
+
+
+<% end %>
diff --git a/vendor/cache/sinclair-b8c88158d000/spec/templates/single_command.xml.erb b/vendor/cache/sinclair-b8c88158d000/spec/templates/single_command.xml.erb
new file mode 100644
index 0000000..3034da1
--- /dev/null
+++ b/vendor/cache/sinclair-b8c88158d000/spec/templates/single_command.xml.erb
@@ -0,0 +1,2 @@
+
+
diff --git a/vendor/cache/timecop-0.8.1.gem b/vendor/cache/timecop-0.8.1.gem
new file mode 100644
index 0000000..a284330
Binary files /dev/null and b/vendor/cache/timecop-0.8.1.gem differ
diff --git a/vendor/cache/websocket-1.2.3.gem b/vendor/cache/websocket-1.2.3.gem
new file mode 100644
index 0000000..b83730b
Binary files /dev/null and b/vendor/cache/websocket-1.2.3.gem differ