agcod 0.0.2
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.
- data/.document +5 -0
- data/.gitignore +9 -0
- data/LICENSE +20 -0
- data/README.rdoc +7 -0
- data/Rakefile +67 -0
- data/VERSION +1 -0
- data/agcod.gemspec +73 -0
- data/cucumber.yml +1 -0
- data/features/error_handling.feature +31 -0
- data/features/step_definitions/agcod_steps.rb +121 -0
- data/features/success_certification.feature +47 -0
- data/features/support/app_root/config/agcod.example.yml +6 -0
- data/features/support/env.rb +8 -0
- data/lib/agcod.rb +25 -0
- data/lib/agcod/cancel_gift_card.rb +21 -0
- data/lib/agcod/configuration.rb +76 -0
- data/lib/agcod/create_gift_card.rb +90 -0
- data/lib/agcod/error/configuration_error.rb +7 -0
- data/lib/agcod/error/invalid_parameter.rb +7 -0
- data/lib/agcod/health_check.rb +8 -0
- data/lib/agcod/option_validators.rb +33 -0
- data/lib/agcod/request.rb +153 -0
- data/lib/agcod/tasks.rb +3 -0
- data/lib/agcod/tasks/certification.rake +45 -0
- data/lib/agcod/void_gift_card_creation.rb +14 -0
- data/manual_features/cancel_claimed_giftcard.feature +13 -0
- data/manual_features/insufficient_funds.feature +13 -0
- data/manual_features/retry_and_http.feature +46 -0
- data/tasks/agcod.rake +1 -0
- data/test/agcod/configuration_test.rb +106 -0
- data/test/app_root/config/agcod.yml +6 -0
- data/test/macros/configuration.rb +24 -0
- data/test/test_helper.rb +25 -0
- metadata +90 -0
data/.document
ADDED
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Dan Pickett
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "agcod"
|
8
|
+
gem.summary = %Q{A Wrapper for Amazon Gift Cards On Demand}
|
9
|
+
gem.email = "dpickett@enlightsolutions.com"
|
10
|
+
gem.homepage = "http://github.com/dpickett/agcod"
|
11
|
+
gem.authors = ["Dan Pickett"]
|
12
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
13
|
+
end
|
14
|
+
|
15
|
+
rescue LoadError
|
16
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
17
|
+
end
|
18
|
+
|
19
|
+
require 'rake/testtask'
|
20
|
+
Rake::TestTask.new(:test) do |test|
|
21
|
+
test.libs << 'lib' << 'test'
|
22
|
+
test.pattern = 'test/**/*_test.rb'
|
23
|
+
test.verbose = true
|
24
|
+
end
|
25
|
+
|
26
|
+
begin
|
27
|
+
require 'rcov/rcovtask'
|
28
|
+
Rcov::RcovTask.new do |test|
|
29
|
+
test.libs << 'test'
|
30
|
+
test.pattern = 'test/**/*_test.rb'
|
31
|
+
test.verbose = true
|
32
|
+
test.rcov_opts << "-x /Gems/"
|
33
|
+
end
|
34
|
+
rescue LoadError
|
35
|
+
task :rcov do
|
36
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
begin
|
41
|
+
require 'cucumber/rake/task'
|
42
|
+
Cucumber::Rake::Task.new(:features)
|
43
|
+
rescue LoadError
|
44
|
+
task :features do
|
45
|
+
abort "Cucumber is not available. In order to run features, you must: sudo gem install cucumber"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
require File.join(File.dirname(__FILE__), "lib", "agcod", "tasks")
|
50
|
+
|
51
|
+
task :default => :spec
|
52
|
+
|
53
|
+
require 'rake/rdoctask'
|
54
|
+
Rake::RDocTask.new do |rdoc|
|
55
|
+
if File.exist?('VERSION.yml')
|
56
|
+
config = YAML.load(File.read('VERSION.yml'))
|
57
|
+
version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
|
58
|
+
else
|
59
|
+
version = ""
|
60
|
+
end
|
61
|
+
|
62
|
+
rdoc.rdoc_dir = 'rdoc'
|
63
|
+
rdoc.title = "agcod #{version}"
|
64
|
+
rdoc.rdoc_files.include('README*')
|
65
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
66
|
+
end
|
67
|
+
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.2
|
data/agcod.gemspec
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{agcod}
|
8
|
+
s.version = "0.0.2"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Dan Pickett"]
|
12
|
+
s.date = %q{2009-10-14}
|
13
|
+
s.email = %q{dpickett@enlightsolutions.com}
|
14
|
+
s.extra_rdoc_files = [
|
15
|
+
"LICENSE",
|
16
|
+
"README.rdoc"
|
17
|
+
]
|
18
|
+
s.files = [
|
19
|
+
".document",
|
20
|
+
".gitignore",
|
21
|
+
"LICENSE",
|
22
|
+
"README.rdoc",
|
23
|
+
"Rakefile",
|
24
|
+
"VERSION",
|
25
|
+
"agcod.gemspec",
|
26
|
+
"cucumber.yml",
|
27
|
+
"features/error_handling.feature",
|
28
|
+
"features/step_definitions/agcod_steps.rb",
|
29
|
+
"features/success_certification.feature",
|
30
|
+
"features/support/app_root/config/agcod.example.yml",
|
31
|
+
"features/support/env.rb",
|
32
|
+
"lib/agcod.rb",
|
33
|
+
"lib/agcod/cancel_gift_card.rb",
|
34
|
+
"lib/agcod/configuration.rb",
|
35
|
+
"lib/agcod/create_gift_card.rb",
|
36
|
+
"lib/agcod/error/configuration_error.rb",
|
37
|
+
"lib/agcod/error/invalid_parameter.rb",
|
38
|
+
"lib/agcod/health_check.rb",
|
39
|
+
"lib/agcod/option_validators.rb",
|
40
|
+
"lib/agcod/request.rb",
|
41
|
+
"lib/agcod/tasks.rb",
|
42
|
+
"lib/agcod/tasks/certification.rake",
|
43
|
+
"lib/agcod/void_gift_card_creation.rb",
|
44
|
+
"manual_features/cancel_claimed_giftcard.feature",
|
45
|
+
"manual_features/insufficient_funds.feature",
|
46
|
+
"manual_features/retry_and_http.feature",
|
47
|
+
"tasks/agcod.rake",
|
48
|
+
"test/agcod/configuration_test.rb",
|
49
|
+
"test/app_root/config/agcod.yml",
|
50
|
+
"test/macros/configuration.rb",
|
51
|
+
"test/test_helper.rb"
|
52
|
+
]
|
53
|
+
s.homepage = %q{http://github.com/dpickett/agcod}
|
54
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
55
|
+
s.require_paths = ["lib"]
|
56
|
+
s.rubygems_version = %q{1.3.5}
|
57
|
+
s.summary = %q{A Wrapper for Amazon Gift Cards On Demand}
|
58
|
+
s.test_files = [
|
59
|
+
"test/agcod/configuration_test.rb",
|
60
|
+
"test/macros/configuration.rb",
|
61
|
+
"test/test_helper.rb"
|
62
|
+
]
|
63
|
+
|
64
|
+
if s.respond_to? :specification_version then
|
65
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
66
|
+
s.specification_version = 3
|
67
|
+
|
68
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
69
|
+
else
|
70
|
+
end
|
71
|
+
else
|
72
|
+
end
|
73
|
+
end
|
data/cucumber.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
default: "--require features/support/env.rb --require features/step_definitions/agcod_steps.rb"
|
@@ -0,0 +1,31 @@
|
|
1
|
+
Feature: Error Handling
|
2
|
+
As a user of the agcod service
|
3
|
+
I want to correctly handle errors
|
4
|
+
So I can get certified
|
5
|
+
|
6
|
+
Background:
|
7
|
+
Given I have access to the AGCOD web service
|
8
|
+
And I am logging transactions
|
9
|
+
|
10
|
+
Scenario: #8 Error Handling E203
|
11
|
+
Given I specify response_id "AAAEPY26ZX1BSY"
|
12
|
+
And I want to cancel request "2"
|
13
|
+
When I send the request
|
14
|
+
Then I should not receive a successful response
|
15
|
+
|
16
|
+
Scenario: #9 Error Handling E204
|
17
|
+
Given I specify response_id "A3REPY26ZX1BSY"
|
18
|
+
And I want to cancel request "2"
|
19
|
+
When I send the request
|
20
|
+
Then I should not receive a successful response
|
21
|
+
|
22
|
+
Scenario: #10 Error Handling for no currency code
|
23
|
+
Given I specify the currency of ""
|
24
|
+
And I want to send request "7"
|
25
|
+
When I send the request
|
26
|
+
Then I should not receive a successful response
|
27
|
+
|
28
|
+
Scenario: #11 Error Handling with Max Limit
|
29
|
+
Given I want to send request "8"
|
30
|
+
When I send the request
|
31
|
+
Then I should not receive a successful response
|
@@ -0,0 +1,121 @@
|
|
1
|
+
Given /^I have access to the AGCOD web service$/ do
|
2
|
+
Agcod::Configuration.load(File.join(File.dirname(__FILE__), "..", "support", "app_root"), "cucumber")
|
3
|
+
assert_not_nil Agcod::Configuration.access_key
|
4
|
+
end
|
5
|
+
|
6
|
+
Given /^I want to send request \"(.*)\"/ do |request_number|
|
7
|
+
req = get_request(request_number)
|
8
|
+
@options ||= {}
|
9
|
+
@request = Agcod::CreateGiftCard.new(req.merge(@options))
|
10
|
+
end
|
11
|
+
|
12
|
+
Given /^I am logging transactions$/ do
|
13
|
+
@logger = Logger.new(File.join(FileUtils.pwd, "agcod_cucumber.log"))
|
14
|
+
Agcod::Configuration.logger = @logger
|
15
|
+
end
|
16
|
+
|
17
|
+
Given /^I want to send a health check request$/ do
|
18
|
+
@request = Agcod::HealthCheck.new
|
19
|
+
end
|
20
|
+
|
21
|
+
Given /^I've sent request \"(.*)\"$/ do |request_number|
|
22
|
+
req = get_request(request_number)
|
23
|
+
@prior_request = Agcod::CreateGiftCard.new("value" => req["value"].to_f,
|
24
|
+
"request_id" => req["request_id"])
|
25
|
+
@prior_request.submit
|
26
|
+
dump_request(@prior_request)
|
27
|
+
end
|
28
|
+
|
29
|
+
Given /^I want to cancel the gift card requested$/ do
|
30
|
+
@request = Agcod::CancelGiftCard.new("request_id" => @prior_request.request_id,
|
31
|
+
"response_id" => @prior_request.response_id)
|
32
|
+
end
|
33
|
+
|
34
|
+
Given /^I want to void the gift card requested$/ do
|
35
|
+
@request = Agcod::VoidGiftCardCreation.new("request_id" => @prior_request.request_id)
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
Given /^the request was successful$/ do
|
40
|
+
assert @prior_request.successful?
|
41
|
+
end
|
42
|
+
|
43
|
+
Given /^I want to create a gift card with the same request id$/ do
|
44
|
+
@request = Agcod::CreateGiftCard.new("value" => 40, "request_id" => @prior_request.request_id)
|
45
|
+
@dont_dump_request = true
|
46
|
+
end
|
47
|
+
|
48
|
+
Given /^I want to cancel request "([^\"]*)"$/ do |req_num|
|
49
|
+
req = get_request(req_num)
|
50
|
+
@options ||= {}
|
51
|
+
@request = Agcod::CancelGiftCard.new(req.merge(@options))
|
52
|
+
end
|
53
|
+
|
54
|
+
Given /^I want to void request "([^\"]*)"$/ do |req_num|
|
55
|
+
req = get_request(req_num)
|
56
|
+
@options ||= {}
|
57
|
+
@request = Agcod::VoidGiftCardCreation.new(req.merge(@options))
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
Given /^I specify response_id "([^\"]*)"$/ do |response_id|
|
62
|
+
@options ||= {}
|
63
|
+
@options["response_id"] = response_id
|
64
|
+
end
|
65
|
+
|
66
|
+
Given /^I specify the currency of "([^\"]*)"$/ do |currency|
|
67
|
+
@options ||= {}
|
68
|
+
@options["currency_code"] = currency
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
|
73
|
+
Then /^I should not receive a successful response$/ do
|
74
|
+
assert !@request.successful?
|
75
|
+
end
|
76
|
+
|
77
|
+
When /^I send the request$/ do
|
78
|
+
@request.submit
|
79
|
+
dump_request(@request) if @request.is_a?(Agcod::CreateGiftCard) && !@dont_dump_request
|
80
|
+
@dont_dump_request = false if @dont_dump_request
|
81
|
+
end
|
82
|
+
|
83
|
+
Then /^I should receive a successful response$/ do
|
84
|
+
assert @request.successful?
|
85
|
+
end
|
86
|
+
|
87
|
+
Then /^I should get a response id$/ do
|
88
|
+
assert_not_nil @request.response_id
|
89
|
+
end
|
90
|
+
|
91
|
+
Then /^I should get a claim code$/ do
|
92
|
+
assert_not_nil @request.claim_code
|
93
|
+
end
|
94
|
+
|
95
|
+
|
96
|
+
def cert_fixture(req_num)
|
97
|
+
File.join(
|
98
|
+
File.dirname(__FILE__), "..", "support", "certification_requests", "#{req_num}.yml"
|
99
|
+
)
|
100
|
+
end
|
101
|
+
|
102
|
+
def get_request(req_num)
|
103
|
+
YAML.load(File.read(cert_fixture(req_num)))
|
104
|
+
end
|
105
|
+
|
106
|
+
def dump_request(req)
|
107
|
+
req_num = req.request_id[0..0]
|
108
|
+
|
109
|
+
|
110
|
+
req_hash = {
|
111
|
+
"request_id" => req.request_id,
|
112
|
+
"value" => req.value,
|
113
|
+
"response_id" => req.response_id,
|
114
|
+
"claim_code" => req.claim_code
|
115
|
+
}
|
116
|
+
|
117
|
+
FileUtils.rm_f(cert_fixture(req_num))
|
118
|
+
File.open(cert_fixture(req_num), "w") do |f|
|
119
|
+
f.puts req_hash.to_yaml
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
Feature: Successful Cases for Certification
|
2
|
+
As a user of the AGCOD api
|
3
|
+
I want to run certification tests that create successful responses
|
4
|
+
So that I can be authorized for production access
|
5
|
+
|
6
|
+
Background:
|
7
|
+
Given I have access to the AGCOD web service
|
8
|
+
And I am logging transactions
|
9
|
+
|
10
|
+
Scenario: #1 Successful Health Check
|
11
|
+
Given I want to send a health check request
|
12
|
+
When I send the request
|
13
|
+
Then I should receive a successful response
|
14
|
+
|
15
|
+
Scenario: #2a Successful Creation of a Gift Card for $12
|
16
|
+
Given I want to send request "1"
|
17
|
+
When I send the request
|
18
|
+
Then I should receive a successful response
|
19
|
+
And I should get a claim code
|
20
|
+
|
21
|
+
Scenario: #2b Successful Creation of a Gift Card for $999
|
22
|
+
Given I want to send request "2"
|
23
|
+
When I send the request
|
24
|
+
Then I should receive a successful response
|
25
|
+
And I should get a claim code
|
26
|
+
|
27
|
+
Scenario: #3 Sending the same Gift Card Request ID
|
28
|
+
Given I've sent request "3"
|
29
|
+
And the request was successful
|
30
|
+
And I want to create a gift card with the same request id
|
31
|
+
When I send the request
|
32
|
+
Then I should not receive a successful response
|
33
|
+
|
34
|
+
Scenario: #4 Cancel a Gift Card Successfully
|
35
|
+
Given I've sent request "4"
|
36
|
+
And the request was successful
|
37
|
+
And I want to cancel the gift card requested
|
38
|
+
When I send the request
|
39
|
+
Then I should receive a successful response
|
40
|
+
|
41
|
+
Scenario: #5 Void a Gift Card Successfully
|
42
|
+
Given I've sent request "5"
|
43
|
+
And the request was successful
|
44
|
+
And I want to void the gift card requested
|
45
|
+
When I send the request
|
46
|
+
Then I should receive a successful response
|
47
|
+
|
data/lib/agcod.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
2
|
+
|
3
|
+
require "net/http"
|
4
|
+
require "net/https"
|
5
|
+
require 'rexml/document'
|
6
|
+
|
7
|
+
require "uri"
|
8
|
+
require "cgi"
|
9
|
+
require "base64"
|
10
|
+
require "hmac-sha1"
|
11
|
+
require "digest/sha1"
|
12
|
+
require "cgi"
|
13
|
+
require "logger"
|
14
|
+
|
15
|
+
require "agcod/error/invalid_parameter"
|
16
|
+
require "agcod/error/configuration_error"
|
17
|
+
require "agcod/option_validators"
|
18
|
+
|
19
|
+
require "agcod/configuration"
|
20
|
+
require "agcod/request"
|
21
|
+
|
22
|
+
require "agcod/cancel_gift_card"
|
23
|
+
require "agcod/create_gift_card"
|
24
|
+
require "agcod/health_check"
|
25
|
+
require "agcod/void_gift_card_creation"
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Agcod
|
2
|
+
class CancelGiftCard < Agcod::Request
|
3
|
+
include Agcod::OptionValidators
|
4
|
+
|
5
|
+
def initialize(options = {})
|
6
|
+
@action = "CancelGiftCard"
|
7
|
+
@required_options = ["request_id", "response_id"]
|
8
|
+
@options = options
|
9
|
+
@required_options.each do |r|
|
10
|
+
validate_length_of(r, "min" => 1, "max" => 19)
|
11
|
+
end
|
12
|
+
|
13
|
+
super
|
14
|
+
|
15
|
+
@parameters["gcCreationRequestId"] = Agcod::Configuration.partner_id.to_s + options["request_id"].to_s
|
16
|
+
@parameters["gcCreationResponseId"] = options["response_id"]
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module Agcod
|
2
|
+
class Configuration
|
3
|
+
REQUIRED_OPTIONS = ["access_key",
|
4
|
+
"secret_key",
|
5
|
+
"partner_id",
|
6
|
+
"uri",
|
7
|
+
"discount_percentage"
|
8
|
+
]
|
9
|
+
|
10
|
+
class << self
|
11
|
+
attr_reader :options
|
12
|
+
attr_accessor :logger
|
13
|
+
|
14
|
+
def load(app_root = nil, env = nil)
|
15
|
+
if app_root
|
16
|
+
@app_root = app_root
|
17
|
+
else
|
18
|
+
@app_root = RAILS_ROOT if defined?(RAILS_ROOT)
|
19
|
+
end
|
20
|
+
|
21
|
+
if @app_root.nil? ||
|
22
|
+
!FileTest.exists?(config_filename = File.join(@app_root, 'config', 'agcod.yml'))
|
23
|
+
|
24
|
+
raise Error::ConfigurationError, "Configuration for AGCOD not found"
|
25
|
+
end
|
26
|
+
|
27
|
+
config_file = File.read(config_filename)
|
28
|
+
|
29
|
+
environment = RAILS_ENV if defined?(RAILS_ENV)
|
30
|
+
environment = env if env
|
31
|
+
|
32
|
+
@options = YAML.load(config_file)[environment]
|
33
|
+
validate_options
|
34
|
+
@options
|
35
|
+
end
|
36
|
+
|
37
|
+
def set(opt = {})
|
38
|
+
@options ||= {}
|
39
|
+
@options.merge!(opt)
|
40
|
+
|
41
|
+
validate_options
|
42
|
+
@options
|
43
|
+
end
|
44
|
+
|
45
|
+
def access_key
|
46
|
+
@options["access_key"]
|
47
|
+
end
|
48
|
+
|
49
|
+
def secret_key
|
50
|
+
@options["secret_key"]
|
51
|
+
end
|
52
|
+
|
53
|
+
def partner_id
|
54
|
+
@options["partner_id"]
|
55
|
+
end
|
56
|
+
|
57
|
+
def uri
|
58
|
+
@options["uri"]
|
59
|
+
end
|
60
|
+
|
61
|
+
def discount_percentage
|
62
|
+
@options["discount_percentage"]
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def validate_options
|
68
|
+
REQUIRED_OPTIONS.each do |opt|
|
69
|
+
if options[opt].nil? || options[opt] == ""
|
70
|
+
raise Error::ConfigurationError, "#{opt} was not specified"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
module Agcod
|
2
|
+
class CreateGiftCard < Agcod::Request
|
3
|
+
include Agcod::OptionValidators
|
4
|
+
|
5
|
+
def initialize(options = {})
|
6
|
+
@action = "CreateGiftCard"
|
7
|
+
super
|
8
|
+
|
9
|
+
validate_greater_than("value", 0)
|
10
|
+
validate_length_of("request_id", {"max" => 19, "min" => 1})
|
11
|
+
|
12
|
+
#can't have a nonexistant or 0 value for the gift card
|
13
|
+
@parameters["gcValue.amount"] = options["value"]
|
14
|
+
|
15
|
+
@value = options["value"]
|
16
|
+
|
17
|
+
#must have a unique identifier for the request
|
18
|
+
@parameters["gcCreationRequestId"] = Agcod::Configuration.partner_id + options["request_id"].to_s
|
19
|
+
|
20
|
+
@parameters["gcValue.currencyCode"] = options["currency_code"] || "USD"
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
def process_response
|
25
|
+
super
|
26
|
+
if self.successful?
|
27
|
+
@claim_code = self.xml_response.root.elements["gcClaimCode"].text
|
28
|
+
@response_id = self.xml_response.root.elements["gcCreationResponseId"].text
|
29
|
+
else
|
30
|
+
attempt_retry unless @sent_retry
|
31
|
+
if @sent_retry
|
32
|
+
void_on_resend
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
attr_reader :claim_code, :response_id, :value
|
38
|
+
|
39
|
+
def to_yaml(name)
|
40
|
+
{"response_id" => self.response_id,
|
41
|
+
"request_id" => self.request_id,
|
42
|
+
"claim_code" => self.claim_code,
|
43
|
+
"value" => self.value,
|
44
|
+
"timestamp" => self.timestamp
|
45
|
+
}.to_yaml(name)
|
46
|
+
end
|
47
|
+
|
48
|
+
protected
|
49
|
+
def send_request
|
50
|
+
begin
|
51
|
+
super
|
52
|
+
rescue SocketError,
|
53
|
+
Timeout::Error,
|
54
|
+
ActiveResource::TimeoutError,
|
55
|
+
Errno::ECONNREFUSED,
|
56
|
+
Errno::EHOSTDOWN,
|
57
|
+
Errno::EHOSTUNREACH
|
58
|
+
|
59
|
+
attempt_to_void
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def attempt_retry
|
64
|
+
#check for retry error
|
65
|
+
if self.xml_response.root.elements["Status/errorCode"] &&
|
66
|
+
self.xml_response.root.elements["Status/errorCode"].text == "E100" &&
|
67
|
+
!@sent_retry
|
68
|
+
|
69
|
+
@sent_retry = true
|
70
|
+
submit
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
def void_on_resend
|
76
|
+
if self.xml_response.root.elements["Status/errorCode"] &&
|
77
|
+
self.xml_response.root.elements["Status/errorCode"].text == "E100" &&
|
78
|
+
!@resend_void_sent
|
79
|
+
|
80
|
+
@resend_void_sent = true
|
81
|
+
attempt_to_void
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def attempt_to_void
|
86
|
+
Agcod::VoidGiftCardCreation.new("request_id" => self.request_id).submit
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Agcod
|
2
|
+
module OptionValidators
|
3
|
+
def validate_timestamp
|
4
|
+
if @options["timestamp"].nil? || !@options["timestamp"].instance_of?(Time)
|
5
|
+
raise Agcod::Error::InvalidParameter, "Invalid Timestamp for record #{@options["record_id"]}"
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
def validate_presence_of(option_name)
|
11
|
+
if @options[option_name].nil? || @options[option_name].to_s.blank?
|
12
|
+
raise Agcod::Error::InvalidParameter, "#{option_name} not specified"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def validate_length_of(option_name, size_options)
|
17
|
+
size_options["min"] ||= 0
|
18
|
+
size_options["max"] ||= 10000
|
19
|
+
if @options[option_name].nil? ||
|
20
|
+
@options[option_name].to_s.size < size_options["min"] ||
|
21
|
+
@options[option_name].to_s.size > size_options["max"]
|
22
|
+
|
23
|
+
raise Agcod::Error::InvalidParameter, "#{option_name} has an invalid length"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def validate_greater_than(option_name, number)
|
28
|
+
if @options[option_name].nil? || @options[option_name].to_f <= number
|
29
|
+
raise Agcod::Error::InvalidParameter, "#{option_name} must be greater than #{number} for record #{@options["record_id"]}"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,153 @@
|
|
1
|
+
module Agcod
|
2
|
+
class Request
|
3
|
+
def initialize(options = {})
|
4
|
+
@request = ""
|
5
|
+
@response = ""
|
6
|
+
@status = ""
|
7
|
+
@parameters = {}
|
8
|
+
@options = options
|
9
|
+
end
|
10
|
+
|
11
|
+
def submit
|
12
|
+
#action must be specified so raise an exception if it has not been populated
|
13
|
+
if self.action.nil?
|
14
|
+
raise "Action not specified"
|
15
|
+
end
|
16
|
+
|
17
|
+
#form the request GET parameter string
|
18
|
+
@request = build_sorted_and_signed_request_string
|
19
|
+
|
20
|
+
send_request
|
21
|
+
|
22
|
+
if @response
|
23
|
+
process_response
|
24
|
+
log if Agcod::Configuration.logger
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def successful?
|
29
|
+
self.sent && self.errors.size == 0 && self.status == "SUCCESS"
|
30
|
+
end
|
31
|
+
|
32
|
+
attr_reader :errors, :request_id, :sent, :action, :request, :parameters, :response, :xml_response, :status, :timestamp
|
33
|
+
|
34
|
+
def sign_string(string_to_sign)
|
35
|
+
#remove all the = and & from the serialized string
|
36
|
+
sanitized_string = string_to_sign.gsub(/=|&/, "")
|
37
|
+
# puts sanitized_string
|
38
|
+
sha1 = HMAC::SHA1::digest(Agcod::Configuration.secret_key, sanitized_string)
|
39
|
+
|
40
|
+
#Base64 encoding adds a linefeed to the end of the string so chop the last character!
|
41
|
+
CGI.escape(Base64.encode64(sha1).chomp)
|
42
|
+
end
|
43
|
+
|
44
|
+
def request_id
|
45
|
+
@options["request_id"]
|
46
|
+
end
|
47
|
+
|
48
|
+
def response_id
|
49
|
+
@response_id || @options["response_id"]
|
50
|
+
end
|
51
|
+
|
52
|
+
protected
|
53
|
+
|
54
|
+
def process_response
|
55
|
+
parse_response
|
56
|
+
|
57
|
+
|
58
|
+
@errors = []
|
59
|
+
|
60
|
+
self.xml_response.root.elements.each("Error") do |e|
|
61
|
+
@errors << e.elements["Message"].text
|
62
|
+
end
|
63
|
+
|
64
|
+
@status = self.xml_response.root.elements["Status/statusCode"].text unless xml_response.root.elements["Status/statusCode"].nil?
|
65
|
+
|
66
|
+
#something happened before it got to ACGWS (most likely a signature problem)
|
67
|
+
@status = "FAILURE" if self.errors.size > 0 && self.status.blank?
|
68
|
+
|
69
|
+
@request_id = xml_response.root.elements["RequestID"].text unless xml_response.root.elements["RequestID"].nil?
|
70
|
+
end
|
71
|
+
|
72
|
+
def parse_response
|
73
|
+
@xml_response ||= REXML::Document.new(self.response)
|
74
|
+
end
|
75
|
+
|
76
|
+
def attempt_retry
|
77
|
+
#check for retry error
|
78
|
+
if self.xml_response.root.elements["Status/errorCode"] &&
|
79
|
+
self.xml_response.root.elements["Status/errorCode"].text == "E100" &&
|
80
|
+
!@sent_retry
|
81
|
+
|
82
|
+
@sent_retry = true
|
83
|
+
submit
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
protected
|
88
|
+
def send_request
|
89
|
+
#send the request
|
90
|
+
uri = URI.parse(Agcod::Configuration.uri)
|
91
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
92
|
+
http.read_timeout = 20
|
93
|
+
http.open_timeout = 20
|
94
|
+
http.use_ssl = true
|
95
|
+
|
96
|
+
net_response, @response = http.get(uri.path + "?" + self.request)
|
97
|
+
|
98
|
+
@sent = true
|
99
|
+
end
|
100
|
+
|
101
|
+
def default_parameters
|
102
|
+
@timestamp = Time.now.utc
|
103
|
+
{
|
104
|
+
"Action" => self.action,
|
105
|
+
"AWSAccessKeyId" => Agcod::Configuration.access_key,
|
106
|
+
"SignatureVersion" => "1",
|
107
|
+
"MessageHeader.recipientId" => "AMAZON",
|
108
|
+
"MessageHeader.sourceId" => Agcod::Configuration.partner_id,
|
109
|
+
"MessageHeader.retryCount" => "0",
|
110
|
+
"MessageHeader.contentVersion" => "2008-01-01",
|
111
|
+
"MessageHeader.messageType" => self.action + "Request",
|
112
|
+
"Timestamp" => @timestamp.strftime("%Y-%m-%dT%H:%M:%S") + ".000Z"
|
113
|
+
}
|
114
|
+
end
|
115
|
+
|
116
|
+
def build_sorted_and_signed_request_string
|
117
|
+
params_to_submit = default_parameters.merge(self.parameters)
|
118
|
+
|
119
|
+
unencoded_key_value_strings = []
|
120
|
+
encoded_key_value_strings = []
|
121
|
+
sort_parameters(params_to_submit).each do |p|
|
122
|
+
unencoded_key_value_strings << p[0].to_s + p[1].to_s
|
123
|
+
|
124
|
+
if p[0] =~ /Timestamp/i
|
125
|
+
encoded_value = p[1]
|
126
|
+
else
|
127
|
+
encoded_value = CGI.escape(p[1].to_s)
|
128
|
+
end
|
129
|
+
encoded_key_value_strings << p[0].to_s + "=" + encoded_value
|
130
|
+
end
|
131
|
+
|
132
|
+
signature = sign_string(unencoded_key_value_strings.join(""))
|
133
|
+
encoded_key_value_strings.insert(encoded_key_value_strings.index("SignatureVersion=1") + 1 , "Signature=" + signature)
|
134
|
+
encoded_key_value_strings.join("&")
|
135
|
+
end
|
136
|
+
|
137
|
+
|
138
|
+
def sort_parameters(params)
|
139
|
+
params.sort{|a, b| a[0].downcase <=> b[0].downcase }
|
140
|
+
end
|
141
|
+
|
142
|
+
def log
|
143
|
+
log_string = "[AGCOD] #{self.action} Request"
|
144
|
+
log_string << " \##{self.request_id}" if self.request_id
|
145
|
+
log_string << " received response #{self.response_id}" if self.response_id
|
146
|
+
if self.respond_to?(:claim_code) && self.claim_code
|
147
|
+
log_string << " received claim_code #{self.claim_code}"
|
148
|
+
end
|
149
|
+
Agcod::Configuration.logger.debug log_string
|
150
|
+
end
|
151
|
+
|
152
|
+
end
|
153
|
+
end
|
data/lib/agcod/tasks.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
require "fileutils"
|
2
|
+
|
3
|
+
namespace :agcod do
|
4
|
+
namespace :certification do
|
5
|
+
desc "generate a request manifest for certification"
|
6
|
+
task :generate_manifest do
|
7
|
+
puts "generating manifest"
|
8
|
+
i = 1
|
9
|
+
prices = [
|
10
|
+
12,
|
11
|
+
999,
|
12
|
+
100,
|
13
|
+
50.02,
|
14
|
+
999.99,
|
15
|
+
600,
|
16
|
+
70,
|
17
|
+
100000,
|
18
|
+
12,
|
19
|
+
12,
|
20
|
+
1
|
21
|
+
]
|
22
|
+
|
23
|
+
path = File.join(FileUtils.pwd, "features", "support", "certification_requests")
|
24
|
+
FileUtils.rm_rf(path)
|
25
|
+
FileUtils.mkdir_p(path)
|
26
|
+
|
27
|
+
requests = []
|
28
|
+
prices.each do |p|
|
29
|
+
random_string_of_numbers = ""
|
30
|
+
12.times {random_string_of_numbers << rand(9).to_s}
|
31
|
+
|
32
|
+
request = {"value" => p,
|
33
|
+
"request_id" => i.to_s + random_string_of_numbers}
|
34
|
+
|
35
|
+
File.open(File.join(path, "#{i}.yml"), 'w') do |manifest|
|
36
|
+
manifest.puts request.to_yaml
|
37
|
+
end
|
38
|
+
i += 1
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
puts "Manifest available at #{path}"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Agcod
|
2
|
+
class VoidGiftCardCreation < Agcod::Request
|
3
|
+
include Agcod::OptionValidators
|
4
|
+
|
5
|
+
def initialize(options = {})
|
6
|
+
@action = "VoidGiftCardCreation"
|
7
|
+
super
|
8
|
+
|
9
|
+
validate_presence_of("request_id")
|
10
|
+
|
11
|
+
@parameters["gcCreationRequestId"] = Agcod::Configuration.partner_id.to_s + self.request_id.to_s
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
Feature: Cancel claimed Gift Card Error Handling
|
2
|
+
As a user of the agcod service
|
3
|
+
I want to handle when I attempt to cancel a claimed gift card
|
4
|
+
So I can get certified
|
5
|
+
|
6
|
+
Background:
|
7
|
+
Given I have access to the AGCOD web service
|
8
|
+
And I am logging transactions
|
9
|
+
|
10
|
+
Scenario: Claimed Gift Card
|
11
|
+
Given I want to cancel request "1"
|
12
|
+
When I send the request
|
13
|
+
Then I should not receive a successful response
|
@@ -0,0 +1,13 @@
|
|
1
|
+
Feature: Insufficient Funds
|
2
|
+
As a user of the agcod service
|
3
|
+
I want to handle when I have insufficient funds appropriately
|
4
|
+
So I can get certified
|
5
|
+
|
6
|
+
Background:
|
7
|
+
Given I have access to the AGCOD web service
|
8
|
+
And I am logging transactions
|
9
|
+
|
10
|
+
Scenario: Insufficient Funds
|
11
|
+
Given I want to send request "6"
|
12
|
+
And I send the request
|
13
|
+
Then I should not receive a successful response
|
@@ -0,0 +1,46 @@
|
|
1
|
+
Feature: Retry responses and HTTP Errors
|
2
|
+
As a user of AGCOD
|
3
|
+
I want to properly handle retry responses and HTTP errors
|
4
|
+
So that I can get certified
|
5
|
+
|
6
|
+
Background:
|
7
|
+
Given I have access to the AGCOD web service
|
8
|
+
And I am logging transactions
|
9
|
+
|
10
|
+
Scenario: #12 RESEND creation request
|
11
|
+
Given I want to send request "9"
|
12
|
+
When I send the request
|
13
|
+
Then I should not receive a successful response
|
14
|
+
|
15
|
+
Scenario: #13 RESEND cancel request
|
16
|
+
Given I want to cancel request "2"
|
17
|
+
When I send the request
|
18
|
+
Then I should not receive a successful response
|
19
|
+
|
20
|
+
Scenario: #14 HTTP error
|
21
|
+
Given I want to send request "10"
|
22
|
+
When I send the request
|
23
|
+
Then I should not receive a successful response
|
24
|
+
|
25
|
+
Scenario: #15 HTTP Void Error
|
26
|
+
Given I want to void request "10"
|
27
|
+
When I send the request
|
28
|
+
Then I should not receive a successful response
|
29
|
+
|
30
|
+
Scenario: #16 HTTP Cancel Error
|
31
|
+
Given I want to cancel request "3"
|
32
|
+
When I send the request
|
33
|
+
Then I should not receive a successful response
|
34
|
+
|
35
|
+
Scenario: #17 minimum amount
|
36
|
+
Given I want to send request "11"
|
37
|
+
When I send the request
|
38
|
+
Then I should not receive a successful response
|
39
|
+
|
40
|
+
Scenario: #17b $12 gift card
|
41
|
+
Given I want to send request "12"
|
42
|
+
When I send the request
|
43
|
+
Then I should receive a successful resposne
|
44
|
+
|
45
|
+
|
46
|
+
|
data/tasks/agcod.rake
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
load File.join(File.dirname(__FILE__), "..", "lib", "agcod", "tasks.rb")
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class Agcod::ConfigurationTest < Test::Unit::TestCase
|
4
|
+
context "an agcod configuration" do
|
5
|
+
setup do
|
6
|
+
@valid_app_root = File.join(File.dirname(__FILE__), "..", "app_root")
|
7
|
+
@valid_options = {
|
8
|
+
"access_key" => "45127185235",
|
9
|
+
"secret_key" => "4321542523453454325j",
|
10
|
+
"partner_id" => "SomebodySpecial",
|
11
|
+
"uri" => "https://agcws-gamma.amazon.com/",
|
12
|
+
"discount_percentage" => 0.04
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
should "raise an error if the configuration file isn't specified" do
|
17
|
+
assert_raise Agcod::Error::ConfigurationError do
|
18
|
+
Agcod::Configuration.load
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
should "raise an error if the configuration file isn't found" do
|
23
|
+
assert_raise Agcod::Error::ConfigurationError do
|
24
|
+
Agcod::Configuration.load("/foo4258fast43")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
should "read configuration from a supplied app root" do
|
29
|
+
Agcod::Configuration.load(File.join(File.dirname(__FILE__), "..", "app_root"), "test")
|
30
|
+
Agcod::Configuration::REQUIRED_OPTIONS.each do |opt|
|
31
|
+
assert_not_nil Agcod::Configuration.send(opt)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
should "allow me to set config options at runtime" do
|
36
|
+
Agcod::Configuration.set(@valid_options)
|
37
|
+
assert_equal Agcod::Configuration.access_key, @valid_options["access_key"]
|
38
|
+
end
|
39
|
+
|
40
|
+
should_require_config_options [
|
41
|
+
"access_key",
|
42
|
+
"secret_key",
|
43
|
+
"partner_id",
|
44
|
+
"uri",
|
45
|
+
"discount_percentage"
|
46
|
+
]
|
47
|
+
end
|
48
|
+
|
49
|
+
context "agcod logging" do
|
50
|
+
setup do
|
51
|
+
configure_with_valid_options
|
52
|
+
@log_path = File.join(File.dirname(__FILE__), "..", "log", "test.log")
|
53
|
+
FileUtils.touch(@log_path)
|
54
|
+
@logger = Logger.new(@log_path)
|
55
|
+
@logger.level = Logger::DEBUG
|
56
|
+
|
57
|
+
Agcod::Configuration.logger = @logger
|
58
|
+
|
59
|
+
FakeWeb.allow_net_connect = false
|
60
|
+
|
61
|
+
@request = Agcod::CreateGiftCard.new("request_id" => 34234, "value" => 12)
|
62
|
+
@request.stubs(:response_id).returns(4323535)
|
63
|
+
@request.stubs(:send_request)
|
64
|
+
@request.stubs(:process_response)
|
65
|
+
@request.stubs(:claim_code).returns(342145)
|
66
|
+
@request.submit
|
67
|
+
end
|
68
|
+
|
69
|
+
teardown do
|
70
|
+
FileUtils.rm_f(@log_path)
|
71
|
+
end
|
72
|
+
|
73
|
+
should "allow me to define a logger for logging requests" do
|
74
|
+
@logger = Logger.new(STDOUT)
|
75
|
+
Agcod::Configuration.logger = @logger
|
76
|
+
assert_equal @logger, Agcod::Configuration.logger
|
77
|
+
end
|
78
|
+
|
79
|
+
should "log request operation names" do
|
80
|
+
assert_match /CreateGiftCard/, File.read(@log_path)
|
81
|
+
end
|
82
|
+
|
83
|
+
should "log request ids when applicable" do
|
84
|
+
assert_match /#{@request.request_id}/, File.read(@log_path)
|
85
|
+
end
|
86
|
+
|
87
|
+
should "log response ids when applicable" do
|
88
|
+
assert_match /#{@request.response_id}/, File.read(@log_path)
|
89
|
+
end
|
90
|
+
|
91
|
+
should "og claim code when applicable" do
|
92
|
+
assert_match /#{@request.claim_code}/, File.read(@log_path)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def configure_with_valid_options
|
97
|
+
@valid_options = {
|
98
|
+
"access_key" => "45127185235",
|
99
|
+
"secret_key" => "4321542523453454325j",
|
100
|
+
"partner_id" => "SomebodySpecial",
|
101
|
+
"uri" => "https://agcws-gamma.amazon.com/",
|
102
|
+
"discount_percentage" => 0.04
|
103
|
+
}
|
104
|
+
Agcod::Configuration.set(@valid_options)
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
class Test::Unit::TestCase
|
2
|
+
def self.should_require_config_options(options)
|
3
|
+
valid_options = {
|
4
|
+
"access_key" => "45127185235",
|
5
|
+
"secret_key" => "4321542523453454325j",
|
6
|
+
"partner_id" => "SomebodySpecial",
|
7
|
+
"uri" => "https://agcws-gamma.amazon.com/",
|
8
|
+
"discount_percentage" => 0.04
|
9
|
+
}
|
10
|
+
|
11
|
+
options = [options] unless options.is_a?(Array)
|
12
|
+
|
13
|
+
options.each do |option|
|
14
|
+
should "require #{option} as a configuration option" do
|
15
|
+
assert_raise Agcod::Error::ConfigurationError do
|
16
|
+
Agcod::Configuration.set(valid_options.merge({
|
17
|
+
option => ""
|
18
|
+
}))
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'test/unit'
|
3
|
+
require 'shoulda'
|
4
|
+
require 'fakeweb'
|
5
|
+
require 'mocha'
|
6
|
+
|
7
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
8
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
9
|
+
require 'agcod'
|
10
|
+
|
11
|
+
begin require "redgreen" rescue Exception; end
|
12
|
+
|
13
|
+
FakeWeb.allow_net_connect = false
|
14
|
+
|
15
|
+
require "macros/configuration"
|
16
|
+
|
17
|
+
class Test::Unit::TestCase
|
18
|
+
def register_response(path, fixture)
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
def xml_fixture_path(fixture)
|
23
|
+
File.join(File.dirname(__FILE__), "fixtures", "#{fixture}.xml")
|
24
|
+
end
|
25
|
+
end
|
metadata
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: agcod
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Dan Pickett
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-10-14 00:00:00 -04:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description:
|
17
|
+
email: dpickett@enlightsolutions.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- LICENSE
|
24
|
+
- README.rdoc
|
25
|
+
files:
|
26
|
+
- .document
|
27
|
+
- .gitignore
|
28
|
+
- LICENSE
|
29
|
+
- README.rdoc
|
30
|
+
- Rakefile
|
31
|
+
- VERSION
|
32
|
+
- agcod.gemspec
|
33
|
+
- cucumber.yml
|
34
|
+
- features/error_handling.feature
|
35
|
+
- features/step_definitions/agcod_steps.rb
|
36
|
+
- features/success_certification.feature
|
37
|
+
- features/support/app_root/config/agcod.example.yml
|
38
|
+
- features/support/env.rb
|
39
|
+
- lib/agcod.rb
|
40
|
+
- lib/agcod/cancel_gift_card.rb
|
41
|
+
- lib/agcod/configuration.rb
|
42
|
+
- lib/agcod/create_gift_card.rb
|
43
|
+
- lib/agcod/error/configuration_error.rb
|
44
|
+
- lib/agcod/error/invalid_parameter.rb
|
45
|
+
- lib/agcod/health_check.rb
|
46
|
+
- lib/agcod/option_validators.rb
|
47
|
+
- lib/agcod/request.rb
|
48
|
+
- lib/agcod/tasks.rb
|
49
|
+
- lib/agcod/tasks/certification.rake
|
50
|
+
- lib/agcod/void_gift_card_creation.rb
|
51
|
+
- manual_features/cancel_claimed_giftcard.feature
|
52
|
+
- manual_features/insufficient_funds.feature
|
53
|
+
- manual_features/retry_and_http.feature
|
54
|
+
- tasks/agcod.rake
|
55
|
+
- test/agcod/configuration_test.rb
|
56
|
+
- test/app_root/config/agcod.yml
|
57
|
+
- test/macros/configuration.rb
|
58
|
+
- test/test_helper.rb
|
59
|
+
has_rdoc: true
|
60
|
+
homepage: http://github.com/dpickett/agcod
|
61
|
+
licenses: []
|
62
|
+
|
63
|
+
post_install_message:
|
64
|
+
rdoc_options:
|
65
|
+
- --charset=UTF-8
|
66
|
+
require_paths:
|
67
|
+
- lib
|
68
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
69
|
+
requirements:
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: "0"
|
73
|
+
version:
|
74
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
75
|
+
requirements:
|
76
|
+
- - ">="
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: "0"
|
79
|
+
version:
|
80
|
+
requirements: []
|
81
|
+
|
82
|
+
rubyforge_project:
|
83
|
+
rubygems_version: 1.3.5
|
84
|
+
signing_key:
|
85
|
+
specification_version: 3
|
86
|
+
summary: A Wrapper for Amazon Gift Cards On Demand
|
87
|
+
test_files:
|
88
|
+
- test/agcod/configuration_test.rb
|
89
|
+
- test/macros/configuration.rb
|
90
|
+
- test/test_helper.rb
|