klarna-checkout 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.rspec +1 -0
- data/Gemfile +4 -0
- data/Guardfile +5 -0
- data/LICENSE.txt +22 -0
- data/README.md +69 -0
- data/Rakefile +1 -0
- data/klarna-checkout.gemspec +32 -0
- data/lib/klarna/checkout.rb +17 -0
- data/lib/klarna/checkout/address.rb +22 -0
- data/lib/klarna/checkout/cart.rb +21 -0
- data/lib/klarna/checkout/cart_item.rb +27 -0
- data/lib/klarna/checkout/client.rb +57 -0
- data/lib/klarna/checkout/concerns/has_many.rb +19 -0
- data/lib/klarna/checkout/concerns/has_one.rb +17 -0
- data/lib/klarna/checkout/customer.rb +13 -0
- data/lib/klarna/checkout/gui.rb +14 -0
- data/lib/klarna/checkout/merchant.rb +19 -0
- data/lib/klarna/checkout/order.rb +33 -0
- data/lib/klarna/checkout/resource.rb +24 -0
- data/lib/klarna/checkout/version.rb +5 -0
- data/spec/acceptance/create_order_spec.rb +59 -0
- data/spec/acceptance/read_order_spec.rb +30 -0
- data/spec/fixtures/vcr_cassettes/create_order_spec.yml +85 -0
- data/spec/fixtures/vcr_cassettes/read_order_spec.yml +47 -0
- data/spec/lib/klarna/checkout/cart_spec.rb +64 -0
- data/spec/lib/klarna/checkout/client_spec.rb +72 -0
- data/spec/lib/klarna/checkout/order_spec.rb +105 -0
- data/spec/lib/klarna/checkout/version_spec.rb +5 -0
- data/spec/spec_helper.rb +24 -0
- data/spec/support/matchers/have_attribute.rb +34 -0
- data/spec/support/matchers/have_many.rb +17 -0
- data/spec/support/matchers/have_one.rb +17 -0
- metadata +230 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 7e38e512946fd7304c91accccae965f8742e3c99
|
4
|
+
data.tar.gz: 575e40eeb308bede813d8837e379968de3fd478d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 76593c8f81683dbdf32e7a76517ca3dcfc0e8b41abb8cbe2e77831d27d5c2c682e7579d27388b2f0c815cff9519a71097c578ec227408bf405471d9d24d5e91d
|
7
|
+
data.tar.gz: d791fc372219a818af9398670c3f204d161aec6cd129a5504ebbca34659ccccc2bd72f646ce906aa51199d134bf97305bd3e8a50edade37f3f0eabf31b6962e7
|
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/Gemfile
ADDED
data/Guardfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Theodor Tonum
|
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,69 @@
|
|
1
|
+
# Klarna Checkout
|
2
|
+
|
3
|
+
Unofficial Ruby Wrapper for Klarnas Checkout Rest API.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'klarna-checkout'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install klarna-checkout
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
```ruby
|
22
|
+
require 'klarna/checkout'
|
23
|
+
|
24
|
+
client = Klarna::Checkout::Client.new({ shared_secret: 'your-shared-secret' })
|
25
|
+
|
26
|
+
# Initialize an order
|
27
|
+
order = Klarna::Checkout::Order.new({
|
28
|
+
purchase_country: 'NO',
|
29
|
+
purchase_currency: 'NOK',
|
30
|
+
locale: 'nb-no',
|
31
|
+
cart: {
|
32
|
+
items: [{
|
33
|
+
reference: '1123581220325',
|
34
|
+
name: 'Widget',
|
35
|
+
quantity: 1,
|
36
|
+
unit_price: 666,
|
37
|
+
tax_rate: 2500
|
38
|
+
}]
|
39
|
+
},
|
40
|
+
merchant: {
|
41
|
+
id: '1337',
|
42
|
+
terms_uri: 'http://www.example.com/terms',
|
43
|
+
checkout_uri: 'http://www.example.com/checkout',
|
44
|
+
confirmation_uri: 'http://www.example.com/confirmation_uri',
|
45
|
+
push_uri: 'http://www.example.com/push'
|
46
|
+
}
|
47
|
+
})
|
48
|
+
|
49
|
+
# Create the order with Klarna
|
50
|
+
client.create_order(order)
|
51
|
+
order.id # => will output the ID of the order (no other attributes are updated)
|
52
|
+
|
53
|
+
# Read an order from Klarna
|
54
|
+
order = client.read_order("1234ABCD")
|
55
|
+
```
|
56
|
+
|
57
|
+
## TODO
|
58
|
+
|
59
|
+
* Raise exceptions on errors from API
|
60
|
+
* Validation of objects according to documentation
|
61
|
+
* Respect readonly attributes
|
62
|
+
|
63
|
+
## Contributing
|
64
|
+
|
65
|
+
1. Fork it
|
66
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
67
|
+
3. Commit your changes, don't forget to add tests (`git commit -am 'Add some feature'`)
|
68
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
69
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'klarna/checkout/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "klarna-checkout"
|
8
|
+
spec.version = Klarna::Checkout::VERSION
|
9
|
+
spec.authors = ["Theodor Tonum"]
|
10
|
+
spec.email = ["theodor@tonum.no"]
|
11
|
+
spec.description = %q{Ruby Wrapper for Klarna Checkout Rest API}
|
12
|
+
spec.summary = %q{...}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency "faraday"
|
22
|
+
spec.add_dependency "activemodel"
|
23
|
+
|
24
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
25
|
+
spec.add_development_dependency "rake"
|
26
|
+
spec.add_development_dependency "rspec"
|
27
|
+
spec.add_development_dependency "guard"
|
28
|
+
spec.add_development_dependency "guard-rspec"
|
29
|
+
spec.add_development_dependency "webmock"
|
30
|
+
spec.add_development_dependency "vcr"
|
31
|
+
spec.add_development_dependency "shoulda-matchers"
|
32
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require "klarna/checkout/version"
|
2
|
+
require "klarna/checkout/client"
|
3
|
+
|
4
|
+
require "klarna/checkout/resource"
|
5
|
+
|
6
|
+
require "klarna/checkout/address"
|
7
|
+
require "klarna/checkout/cart"
|
8
|
+
require "klarna/checkout/customer"
|
9
|
+
require "klarna/checkout/gui"
|
10
|
+
require "klarna/checkout/merchant"
|
11
|
+
require "klarna/checkout/order"
|
12
|
+
|
13
|
+
module Klarna
|
14
|
+
module Checkout
|
15
|
+
# Your code goes here...
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Klarna
|
2
|
+
module Checkout
|
3
|
+
class Address < Resource
|
4
|
+
attr_accessor :given_name, :family_name, :care_of, :street_address,
|
5
|
+
:postal_code, :city, :country, :email, :phone
|
6
|
+
|
7
|
+
def as_json
|
8
|
+
{
|
9
|
+
:given_name => @given_name,
|
10
|
+
:family_name => @family_name,
|
11
|
+
:care_of => @care_of,
|
12
|
+
:street_address => @street_address,
|
13
|
+
:postal_code => @postal_code,
|
14
|
+
:city => @city,
|
15
|
+
:country => @country,
|
16
|
+
:email => @email,
|
17
|
+
:phone => @phone
|
18
|
+
}
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require "klarna/checkout/cart_item"
|
2
|
+
|
3
|
+
module Klarna
|
4
|
+
module Checkout
|
5
|
+
class Cart < Resource
|
6
|
+
attr_accessor :total_price_including_tax, :total_price_excluding_tax,
|
7
|
+
:total_tax_amount
|
8
|
+
|
9
|
+
has_many :items, Klarna::Checkout::CartItem
|
10
|
+
|
11
|
+
def as_json
|
12
|
+
{
|
13
|
+
:total_price_including_tax => @total_price_including_tax,
|
14
|
+
:total_price_excluding_tax => @total_price_excluding_tax,
|
15
|
+
:total_tax_amount => @total_tax_amount,
|
16
|
+
:items => @items.map(&:as_json)
|
17
|
+
}
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Klarna
|
2
|
+
module Checkout
|
3
|
+
class CartItem < Resource
|
4
|
+
attr_accessor :type, :ean, :reference, :name, :uri, :image_uri, :quantity,
|
5
|
+
:unit_price, :total_price_excluding_tax, :total_tax_amount,
|
6
|
+
:total_price_including_tax, :discount_rate, :tax_rate
|
7
|
+
|
8
|
+
def as_json
|
9
|
+
{
|
10
|
+
:type => @type,
|
11
|
+
:ean => @ean,
|
12
|
+
:reference => @reference,
|
13
|
+
:name => @name,
|
14
|
+
:uri => @uri,
|
15
|
+
:image_uri => @image_uri,
|
16
|
+
:quantity => @quantity,
|
17
|
+
:unit_price => @unit_price,
|
18
|
+
:total_price_excluding_tax => @total_price_excluding_tax,
|
19
|
+
:total_tax_amount => @total_tax_amount,
|
20
|
+
:total_price_including_tax => @total_price_including_tax,
|
21
|
+
:discount_rate => @discount_rate,
|
22
|
+
:tax_rate => @tax_rate
|
23
|
+
}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'digest/sha2'
|
2
|
+
require 'base64'
|
3
|
+
require 'faraday'
|
4
|
+
|
5
|
+
module Klarna
|
6
|
+
module Checkout
|
7
|
+
class Client
|
8
|
+
attr_accessor :shared_secret
|
9
|
+
|
10
|
+
def initialize(args = {})
|
11
|
+
args.each do |(k,v)|
|
12
|
+
self.public_send("#{k}=", v)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def create_order(order)
|
17
|
+
request_body = order.to_json
|
18
|
+
response = https_connection.post do |req|
|
19
|
+
req.url '/checkout/orders'
|
20
|
+
|
21
|
+
req.headers['Authorization'] = "Klarna #{sign_payload(request_body)}"
|
22
|
+
req.headers['Accept'] = 'application/vnd.klarna.checkout.aggregated-order-v2+json',
|
23
|
+
req.headers['Content-Type'] = 'application/vnd.klarna.checkout.aggregated-order-v2+json'
|
24
|
+
req.headers['Accept-Encoding'] = ''
|
25
|
+
|
26
|
+
req.body = request_body
|
27
|
+
end
|
28
|
+
order.id = response.headers['Location'].split('/').last
|
29
|
+
order
|
30
|
+
end
|
31
|
+
|
32
|
+
def read_order(id)
|
33
|
+
response = https_connection.get do |req|
|
34
|
+
req.url "/checkout/orders/#{id}"
|
35
|
+
|
36
|
+
req.headers['Authorization'] = "Klarna #{sign_payload}"
|
37
|
+
req.headers['Accept'] = 'application/vnd.klarna.checkout.aggregated-order-v2+json'
|
38
|
+
req.headers['Accept-Encoding'] = ''
|
39
|
+
end
|
40
|
+
Order.new(JSON.parse(response.body))
|
41
|
+
end
|
42
|
+
|
43
|
+
# Based on example from:
|
44
|
+
# http://developers.klarna.com/en/api-references-v1/klarna-checkout#authorization
|
45
|
+
def sign_payload(request_body = '')
|
46
|
+
payload = "#{request_body}#{shared_secret}"
|
47
|
+
Digest::SHA256.base64digest(payload)
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def https_connection
|
53
|
+
@https_connection ||= Faraday.new(url: 'https://checkout.testdrive.klarna.com')
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module HasMany
|
2
|
+
def has_many(association, klass = nil)
|
3
|
+
attr_accessor association
|
4
|
+
|
5
|
+
define_method "#{association}=" do |new_value|
|
6
|
+
new_value = Array(new_value)
|
7
|
+
inst_var = "@#{association}"
|
8
|
+
case new_value.first
|
9
|
+
when klass
|
10
|
+
instance_variable_set(inst_var, new_value)
|
11
|
+
when Hash
|
12
|
+
new_value = new_value.map { |hash| klass.new(hash) }
|
13
|
+
instance_variable_set(inst_var, new_value)
|
14
|
+
else
|
15
|
+
raise "Unsupported type for relation #{association}: #{new_value.first.class.to_s}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module HasOne
|
2
|
+
def has_one(association, klass = nil)
|
3
|
+
attr_accessor association
|
4
|
+
|
5
|
+
define_method "#{association}=" do |new_value|
|
6
|
+
inst_var = "@#{association}"
|
7
|
+
case new_value
|
8
|
+
when klass
|
9
|
+
instance_variable_set(inst_var, new_value)
|
10
|
+
when Hash
|
11
|
+
instance_variable_set(inst_var, klass.new(new_value))
|
12
|
+
else
|
13
|
+
raise "Unsupported type for relation #{association}: #{new_value.class.to_s}"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Klarna
|
2
|
+
module Checkout
|
3
|
+
class Merchant < Resource
|
4
|
+
attr_accessor :id, :terms_uri, :checkout_uri, :confirmation_uri,
|
5
|
+
:push_uri, :validation_uri
|
6
|
+
|
7
|
+
def as_json
|
8
|
+
{
|
9
|
+
:id => @id,
|
10
|
+
:terms_uri => @terms_uri,
|
11
|
+
:checkout_uri => @checkout_uri,
|
12
|
+
:confirmation_uri => @confirmation_uri,
|
13
|
+
:push_uri => @push_uri,
|
14
|
+
:validation_uri => @validation_uri
|
15
|
+
}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module Klarna
|
4
|
+
module Checkout
|
5
|
+
class Order < Resource
|
6
|
+
attr_accessor :id, :status, :reference, :reservation, :started_at,
|
7
|
+
:completed_at, :created_at, :last_modified_at, :expires_at,
|
8
|
+
:locale
|
9
|
+
|
10
|
+
attr_accessor :merchant_reference, :purchase_country, :purchase_currency
|
11
|
+
|
12
|
+
has_one :billing_address, Klarna::Checkout::Address
|
13
|
+
has_one :shipping_address, Klarna::Checkout::Address
|
14
|
+
has_one :cart, Klarna::Checkout::Cart
|
15
|
+
has_one :customer, Klarna::Checkout::Customer
|
16
|
+
has_one :merchant, Klarna::Checkout::Merchant
|
17
|
+
has_one :gui, Klarna::Checkout::Gui
|
18
|
+
|
19
|
+
def as_json
|
20
|
+
{
|
21
|
+
:merchant_reference => @merchant_reference,
|
22
|
+
:purchase_country => @purchase_country,
|
23
|
+
:purchase_currency => @purchase_currency,
|
24
|
+
:locale => @locale,
|
25
|
+
:cart => @cart.as_json,
|
26
|
+
:merchant => @merchant.as_json
|
27
|
+
}.reject do |k, v|
|
28
|
+
v.nil?
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'klarna/checkout/concerns/has_one'
|
3
|
+
require 'klarna/checkout/concerns/has_many'
|
4
|
+
|
5
|
+
module Klarna
|
6
|
+
module Checkout
|
7
|
+
class Resource
|
8
|
+
extend HasOne
|
9
|
+
extend HasMany
|
10
|
+
|
11
|
+
def initialize(args = {})
|
12
|
+
args.each_pair do |attr, value|
|
13
|
+
setter = "#{attr.to_s}="
|
14
|
+
self.send(setter, value) if respond_to?(setter)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_json
|
19
|
+
sanitized_json = self.as_json.reject { |k, v| v.nil? }
|
20
|
+
JSON.generate(sanitized_json)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "creating/reading order" do
|
4
|
+
around(:each) do |example|
|
5
|
+
VCR.use_cassette('create_order_spec') do
|
6
|
+
example.run
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
let(:client) do
|
11
|
+
Klarna::Checkout::Client.new \
|
12
|
+
shared_secret: 'foobar'
|
13
|
+
end
|
14
|
+
|
15
|
+
context "when I have created an order" do
|
16
|
+
let(:order) do
|
17
|
+
Klarna::Checkout::Order.new \
|
18
|
+
purchase_country: 'NO',
|
19
|
+
purchase_currency: 'NOK',
|
20
|
+
locale: 'nb-no',
|
21
|
+
cart: {
|
22
|
+
items: [{
|
23
|
+
reference: '1123581220325',
|
24
|
+
name: 'Widget',
|
25
|
+
quantity: 1,
|
26
|
+
unit_price: 666,
|
27
|
+
tax_rate: 2500
|
28
|
+
}]
|
29
|
+
},
|
30
|
+
merchant: {
|
31
|
+
id: '1337',
|
32
|
+
terms_uri: 'http://www.example.com/terms',
|
33
|
+
checkout_uri: 'http://www.example.com/checkout',
|
34
|
+
confirmation_uri: 'http://www.example.com/confirmation_uri',
|
35
|
+
push_uri: 'http://www.example.com/push'
|
36
|
+
}
|
37
|
+
end
|
38
|
+
|
39
|
+
before(:each) do
|
40
|
+
client.create_order(order)
|
41
|
+
end
|
42
|
+
|
43
|
+
describe "I should be able to fetch this order and read some attributes" do
|
44
|
+
let(:read_order) { client.read_order(order.id) }
|
45
|
+
subject { read_order }
|
46
|
+
|
47
|
+
it { should_not be_nil }
|
48
|
+
|
49
|
+
its(:id) { should eq order.id }
|
50
|
+
its(:status) { should eq 'checkout_incomplete' }
|
51
|
+
|
52
|
+
describe "cart" do
|
53
|
+
subject { read_order.cart }
|
54
|
+
|
55
|
+
its(:total_price_including_tax) { should eq 666 }
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "reading order" do
|
4
|
+
around(:each) do |example|
|
5
|
+
VCR.use_cassette('read_order_spec') do
|
6
|
+
example.run
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
let(:client) do
|
11
|
+
Klarna::Checkout::Client.new \
|
12
|
+
shared_secret: 'foobar'
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "I should be able to fetch an order and read its attributes" do
|
16
|
+
let(:read_order) { client.read_order('143F7EB92CD90B11C39E7220000') }
|
17
|
+
subject { read_order }
|
18
|
+
|
19
|
+
it { should_not be_nil }
|
20
|
+
|
21
|
+
its(:id) { should eq '143F7EB92CD90B11C39E7220000' }
|
22
|
+
its(:status) { should eq 'checkout_incomplete' }
|
23
|
+
|
24
|
+
describe "cart" do
|
25
|
+
subject { read_order.cart }
|
26
|
+
|
27
|
+
its(:total_price_including_tax) { should eq 666 }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: post
|
5
|
+
uri: https://checkout.testdrive.klarna.com/checkout/orders
|
6
|
+
body:
|
7
|
+
encoding: UTF-8
|
8
|
+
string: '{"purchase_country":"NO","purchase_currency":"NOK","locale":"nb-no","cart":{"items":[{"reference":"1123581220325","name":"Widget","quantity":1,"unit_price":666,"tax_rate":2500}]},"merchant":{"id":"1337","terms_uri":"http://www.example.com/terms","checkout_uri":"http://www.example.com/checkout","confirmation_uri":"http://www.example.com/confirmation_uri","push_uri":"http://www.example.com/push"}}'
|
9
|
+
headers:
|
10
|
+
User-Agent:
|
11
|
+
- Faraday v0.9.0
|
12
|
+
Authorization:
|
13
|
+
- Klarna gone
|
14
|
+
Content-Type:
|
15
|
+
- application/vnd.klarna.checkout.aggregated-order-v2+json
|
16
|
+
Accept:
|
17
|
+
- application/vnd.klarna.checkout.aggregated-order-v2+json, application/vnd.klarna.checkout.aggregated-order-v2+json
|
18
|
+
Accept-Encoding:
|
19
|
+
- ''
|
20
|
+
response:
|
21
|
+
status:
|
22
|
+
code: 201
|
23
|
+
message: Created
|
24
|
+
headers:
|
25
|
+
Server:
|
26
|
+
- MochiWeb/1.1 WebMachine/1.10.0 (never breaks eye contact)
|
27
|
+
Location:
|
28
|
+
- https://checkout.testdrive.klarna.com/checkout/orders/143F7EB92CD90B11C39E7220000
|
29
|
+
Date:
|
30
|
+
- Mon, 03 Feb 2014 13:24:07 GMT
|
31
|
+
Content-Type:
|
32
|
+
- application/vnd.klarna.checkout.aggregated-order-v2+json
|
33
|
+
Content-Length:
|
34
|
+
- '0'
|
35
|
+
Connection:
|
36
|
+
- keep-alive
|
37
|
+
body:
|
38
|
+
encoding: UTF-8
|
39
|
+
string: ''
|
40
|
+
http_version:
|
41
|
+
recorded_at: Mon, 03 Feb 2014 13:24:07 GMT
|
42
|
+
- request:
|
43
|
+
method: get
|
44
|
+
uri: https://checkout.testdrive.klarna.com/checkout/orders/143F7EB92CD90B11C39E7220000
|
45
|
+
body:
|
46
|
+
encoding: US-ASCII
|
47
|
+
string: ''
|
48
|
+
headers:
|
49
|
+
User-Agent:
|
50
|
+
- Faraday v0.9.0
|
51
|
+
Authorization:
|
52
|
+
- Klarna gone
|
53
|
+
Accept:
|
54
|
+
- application/vnd.klarna.checkout.aggregated-order-v2+json
|
55
|
+
Accept-Encoding:
|
56
|
+
- ''
|
57
|
+
response:
|
58
|
+
status:
|
59
|
+
code: 200
|
60
|
+
message: OK
|
61
|
+
headers:
|
62
|
+
Server:
|
63
|
+
- MochiWeb/1.1 WebMachine/1.10.0 (never breaks eye contact)
|
64
|
+
Pragma:
|
65
|
+
- no-cache
|
66
|
+
Date:
|
67
|
+
- Mon, 03 Feb 2014 13:24:08 GMT
|
68
|
+
Content-Type:
|
69
|
+
- application/vnd.klarna.checkout.aggregated-order-v2+json
|
70
|
+
Content-Length:
|
71
|
+
- '2060'
|
72
|
+
Cache-Control:
|
73
|
+
- max-age=0, no-cache, no-store
|
74
|
+
Connection:
|
75
|
+
- keep-alive
|
76
|
+
body:
|
77
|
+
encoding: UTF-8
|
78
|
+
string: '{"id":"143F7EB92CD90B11C39E7220000","purchase_country":"no","purchase_currency":"nok","locale":"nb-no","status":"checkout_incomplete","started_at":"2014-02-03T14:24:07+01:00","last_modified_at":"2014-02-03T14:24:07+01:00","cart":{"total_price_excluding_tax":532,"total_tax_amount":134,"total_price_including_tax":666,"items":[{"reference":"1123581220325","name":"Widget","quantity":1,"unit_price":666,"tax_rate":2500,"discount_rate":0,"type":"physical","total_price_including_tax":666,"total_price_excluding_tax":532,"total_tax_amount":134}]},"customer":{"type":"person"},"shipping_address":{"country":"no"},"billing_address":{"country":"no"},"gui":{"layout":"desktop","snippet":"<div
|
79
|
+
id=\"klarna-checkout-container\" style=\"overflow-x:\nhidden;\"><script type=\"text/javascript\">/*
|
80
|
+
<![CDATA[ */(function(w,k,i,d,u,n,c){w[k]=w[k]||function(){(w[k].q=w[k].q||[]).push(arguments)};w[k].config={container:w.document.getElementById(i),ORDER_URL:''https://checkout.testdrive.klarna.com/checkout/orders/143F7EB92CD90B11C39E7220000'',TESTDRIVE:true,AUTH_HEADER:''KlarnaCheckout
|
81
|
+
Pss54gM64IrvKxHMKUaA'',LAYOUT:''desktop'',LOCALE:''nb-no'',ORDER_STATUS:''checkout_incomplete'',MERCHANT_TAC_URI:''http://www.example.com/terms'',MERCHANT_TAC_TITLE:''test'',MERCHANT_NAME:''test'',GUI_OPTIONS:[],ALLOW_SEPARATE_SHIPPING_ADDRESS:false,PURCHASE_COUNTRY:''nor'',PURCHASE_CURRENCY:''nok'',DISALLOW_SKIP_NIN:false,BOOTSTRAP_SRC:u};n=d.createElement(''script'');c=d.getElementById(i);n.async=!0;n.src=u;c.insertBefore(n,c.firstChild);})(this,''_klarnaCheckout'',''klarna-checkout-container'',document,''https://checkout.testdrive.klarna.com/131022-064eb74/checkout.bootstrap.js'');/*
|
82
|
+
]]> */</script><noscript>Please <a href=\"http://enable-javascript.com\">enable\nJavaScript</a>.</noscript></div>"},"options":{"allow_separate_shipping_address":false},"merchant":{"id":"1337","terms_uri":"http://www.example.com/terms","checkout_uri":"http://www.example.com/checkout","confirmation_uri":"http://www.example.com/confirmation_uri","push_uri":"http://www.example.com/push"}}'
|
83
|
+
http_version:
|
84
|
+
recorded_at: Mon, 03 Feb 2014 13:24:08 GMT
|
85
|
+
recorded_with: VCR 2.8.0
|
@@ -0,0 +1,47 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: https://checkout.testdrive.klarna.com/checkout/orders/143F7EB92CD90B11C39E7220000
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers:
|
10
|
+
User-Agent:
|
11
|
+
- Faraday v0.9.0
|
12
|
+
Authorization:
|
13
|
+
- Klarna gone
|
14
|
+
Accept:
|
15
|
+
- application/vnd.klarna.checkout.aggregated-order-v2+json
|
16
|
+
Accept-Encoding:
|
17
|
+
- ''
|
18
|
+
response:
|
19
|
+
status:
|
20
|
+
code: 200
|
21
|
+
message: OK
|
22
|
+
headers:
|
23
|
+
Server:
|
24
|
+
- MochiWeb/1.1 WebMachine/1.10.0 (never breaks eye contact)
|
25
|
+
Pragma:
|
26
|
+
- no-cache
|
27
|
+
Date:
|
28
|
+
- Tue, 04 Feb 2014 14:49:43 GMT
|
29
|
+
Content-Type:
|
30
|
+
- application/vnd.klarna.checkout.aggregated-order-v2+json
|
31
|
+
Content-Length:
|
32
|
+
- '2060'
|
33
|
+
Cache-Control:
|
34
|
+
- max-age=0, no-cache, no-store
|
35
|
+
Connection:
|
36
|
+
- keep-alive
|
37
|
+
body:
|
38
|
+
encoding: UTF-8
|
39
|
+
string: '{"id":"143F7EB92CD90B11C39E7220000","purchase_country":"no","purchase_currency":"nok","locale":"nb-no","status":"checkout_incomplete","started_at":"2014-02-03T14:24:07+01:00","last_modified_at":"2014-02-03T14:24:07+01:00","cart":{"total_price_excluding_tax":532,"total_tax_amount":134,"total_price_including_tax":666,"items":[{"reference":"1123581220325","name":"Widget","quantity":1,"unit_price":666,"tax_rate":2500,"discount_rate":0,"type":"physical","total_price_including_tax":666,"total_price_excluding_tax":532,"total_tax_amount":134}]},"customer":{"type":"person"},"shipping_address":{"country":"no"},"billing_address":{"country":"no"},"gui":{"layout":"desktop","snippet":"<div
|
40
|
+
id=\"klarna-checkout-container\" style=\"overflow-x:\nhidden;\"><script type=\"text/javascript\">/*
|
41
|
+
<![CDATA[ */(function(w,k,i,d,u,n,c){w[k]=w[k]||function(){(w[k].q=w[k].q||[]).push(arguments)};w[k].config={container:w.document.getElementById(i),ORDER_URL:''https://checkout.testdrive.klarna.com/checkout/orders/143F7EB92CD90B11C39E7220000'',TESTDRIVE:true,AUTH_HEADER:''KlarnaCheckout
|
42
|
+
Pss54gM64IrvKxHMKUaA'',LAYOUT:''desktop'',LOCALE:''nb-no'',ORDER_STATUS:''checkout_incomplete'',MERCHANT_TAC_URI:''http://www.example.com/terms'',MERCHANT_TAC_TITLE:''R\u00f8rkj\u00f8p
|
43
|
+
KCO'',MERCHANT_NAME:''R\u00f8rkj\u00f8p KCO'',GUI_OPTIONS:[],ALLOW_SEPARATE_SHIPPING_ADDRESS:false,PURCHASE_COUNTRY:''nor'',PURCHASE_CURRENCY:''nok'',DISALLOW_SKIP_NIN:false,BOOTSTRAP_SRC:u};n=d.createElement(''script'');c=d.getElementById(i);n.async=!0;n.src=u;c.insertBefore(n,c.firstChild);})(this,''_klarnaCheckout'',''klarna-checkout-container'',document,''https://checkout.testdrive.klarna.com/131022-064eb74/checkout.bootstrap.js'');/*
|
44
|
+
]]> */</script><noscript>Please <a href=\"http://enable-javascript.com\">enable\nJavaScript</a>.</noscript></div>"},"options":{"allow_separate_shipping_address":false},"merchant":{"id":"1337","terms_uri":"http://www.example.com/terms","checkout_uri":"http://www.example.com/checkout","confirmation_uri":"http://www.example.com/confirmation_uri","push_uri":"http://www.example.com/push"}}'
|
45
|
+
http_version:
|
46
|
+
recorded_at: Tue, 04 Feb 2014 14:49:43 GMT
|
47
|
+
recorded_with: VCR 2.8.0
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Klarna::Checkout::Cart do
|
4
|
+
describe "attributes" do
|
5
|
+
it { should have_attribute(:total_price_including_tax) }
|
6
|
+
it { should have_attribute(:total_price_excluding_tax) }
|
7
|
+
it { should have_attribute(:total_tax_amount) }
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "relations" do
|
11
|
+
it { should have_many(:items, as: Klarna::Checkout::CartItem) }
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "#as_json" do
|
15
|
+
let(:cart) do
|
16
|
+
described_class.new \
|
17
|
+
total_price_including_tax: 250,
|
18
|
+
total_price_excluding_tax: 200,
|
19
|
+
total_tax_amount: 50,
|
20
|
+
items: [{
|
21
|
+
type: 'physical',
|
22
|
+
ean: '1123581220325',
|
23
|
+
reference: '1123581220325',
|
24
|
+
name: 'Widget',
|
25
|
+
uri: 'http://www.example.com/product-uri',
|
26
|
+
image_uri: 'http://www.example.com/product-image-uri',
|
27
|
+
quantity: 1,
|
28
|
+
unit_price: 250,
|
29
|
+
total_price_excluding_tax: 200,
|
30
|
+
total_tax_amount: 50,
|
31
|
+
total_price_including_tax: 250,
|
32
|
+
discount_rate: 0,
|
33
|
+
tax_rate: 2500
|
34
|
+
}]
|
35
|
+
end
|
36
|
+
|
37
|
+
let(:json_hash) { cart.as_json }
|
38
|
+
subject do
|
39
|
+
json_hash
|
40
|
+
end
|
41
|
+
|
42
|
+
its([:total_price_including_tax]) { should eq 250 }
|
43
|
+
its([:total_price_excluding_tax]) { should eq 200 }
|
44
|
+
its([:total_tax_amount]) { should eq 50 }
|
45
|
+
|
46
|
+
describe "items/0" do
|
47
|
+
subject { json_hash[:items][0] }
|
48
|
+
|
49
|
+
its([:type]) { should eq 'physical' }
|
50
|
+
its([:ean]) { should eq '1123581220325' }
|
51
|
+
its([:reference]) { should eq '1123581220325' }
|
52
|
+
its([:name]) { should eq 'Widget' }
|
53
|
+
its([:uri]) { should eq 'http://www.example.com/product-uri' }
|
54
|
+
its([:image_uri]) { should eq 'http://www.example.com/product-image-uri' }
|
55
|
+
its([:quantity]) { should eq 1 }
|
56
|
+
its([:unit_price]) { should eq 250 }
|
57
|
+
its([:total_price_excluding_tax]) { should eq 200 }
|
58
|
+
its([:total_tax_amount]) { should eq 50 }
|
59
|
+
its([:total_price_including_tax]) { should eq 250 }
|
60
|
+
its([:discount_rate]) { should eq 0 }
|
61
|
+
its([:tax_rate]) { should eq 2500 }
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
describe Klarna::Checkout::Client do
|
5
|
+
describe ".new" do
|
6
|
+
subject do
|
7
|
+
described_class.new({
|
8
|
+
shared_secret: 'foobar'
|
9
|
+
})
|
10
|
+
end
|
11
|
+
|
12
|
+
its(:shared_secret) { should eq 'foobar' }
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "#create_order" do
|
16
|
+
subject { described_class.new({shared_secret: 'foobar'}) }
|
17
|
+
|
18
|
+
let(:order) { double('Order', to_json: JSON.generate({ foo: "bar" }), :id= => true) }
|
19
|
+
|
20
|
+
it "sends a json representation of the object to Klarna" do
|
21
|
+
stub_request(:post, "https://checkout.testdrive.klarna.com/checkout/orders")
|
22
|
+
.to_return(headers: { 'Location' => 'https://checkout.testdrive.klarna.com/checkout/orders/143F7BC0A1090B11C39E7220000' })
|
23
|
+
|
24
|
+
subject.create_order(order)
|
25
|
+
|
26
|
+
assert_requested :post, "https://checkout.testdrive.klarna.com/checkout/orders",
|
27
|
+
:headers => {
|
28
|
+
# TODO: Investigate double definition in header
|
29
|
+
# 'Accept' => 'application/vnd.klarna.checkout.aggregated-order-v2+json',
|
30
|
+
'Authorization' => 'Klarna dM+worqeBUs4UrOB3Jr/jSZWI39vP4LNw7NfDjGtW2w=',
|
31
|
+
'Content-Type' => 'application/vnd.klarna.checkout.aggregated-order-v2+json',
|
32
|
+
},
|
33
|
+
:body => JSON.generate({ foo: "bar" }),
|
34
|
+
:times => 1
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "#read_order" do
|
39
|
+
subject { described_class.new({shared_secret: 'foobar'}) }
|
40
|
+
|
41
|
+
it "uses the correct endpoint at klarna" do
|
42
|
+
stub_request(:get, "https://checkout.testdrive.klarna.com/checkout/orders/143F7BC0A1090B11C39E7220000")
|
43
|
+
.to_return(body: JSON.generate({ id: "143F7BC0A1090B11C39E7220000" }))
|
44
|
+
|
45
|
+
subject.read_order('143F7BC0A1090B11C39E7220000')
|
46
|
+
|
47
|
+
assert_requested :get, "https://checkout.testdrive.klarna.com/checkout/orders/143F7BC0A1090B11C39E7220000",
|
48
|
+
:headers => {
|
49
|
+
# TODO: Investigate double definition in header
|
50
|
+
# 'Accept' => 'application/vnd.klarna.checkout.aggregated-order-v2+json',
|
51
|
+
'Authorization' => 'Klarna w6uP8Tcg6K2QR905Rms8iXTlksL6OD1KOWBxTK7wxPI=',
|
52
|
+
},
|
53
|
+
:times => 1
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "#sign_payload" do
|
58
|
+
let(:client) { described_class.new(shared_secret: 'foobar') }
|
59
|
+
|
60
|
+
context "when request body is empty" do
|
61
|
+
subject { client.sign_payload }
|
62
|
+
|
63
|
+
it { should eq "w6uP8Tcg6K2QR905Rms8iXTlksL6OD1KOWBxTK7wxPI=" }
|
64
|
+
end
|
65
|
+
|
66
|
+
context "when request body has some content" do
|
67
|
+
subject { client.sign_payload('{"foo":"bar"}') }
|
68
|
+
|
69
|
+
it { should eq "dM+worqeBUs4UrOB3Jr/jSZWI39vP4LNw7NfDjGtW2w=" }
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Klarna::Checkout::Order do
|
4
|
+
describe ".initialize" do
|
5
|
+
subject do
|
6
|
+
described_class.new \
|
7
|
+
id: 1,
|
8
|
+
status: 'foo'
|
9
|
+
end
|
10
|
+
|
11
|
+
its(:id) { should eq 1 }
|
12
|
+
its(:status) { should eq 'foo' }
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "attributes" do
|
16
|
+
it { should have_attribute(:id) } #, :readonly) }
|
17
|
+
it { should have_attribute(:merchant_reference) } #, :optional) }
|
18
|
+
it { should have_attribute(:purchase_country) } #, :mandatory) }
|
19
|
+
it { should have_attribute(:purchase_currency) } #, :mandatory) }
|
20
|
+
it { should have_attribute(:locale) } #, :mandatory) }
|
21
|
+
it { should have_attribute(:status) } #, :readonly) }
|
22
|
+
it { should have_attribute(:reference) } #, :readonly) }
|
23
|
+
it { should have_attribute(:reservation) } #, :readonly) }
|
24
|
+
it { should have_attribute(:started_at) } #, :readonly) }
|
25
|
+
it { should have_attribute(:completed_at) } #, :readonly) }
|
26
|
+
it { should have_attribute(:created_at) } #, :readonly) }
|
27
|
+
it { should have_attribute(:last_modified_at) } #, :readonly) }
|
28
|
+
it { should have_attribute(:expires_at) } #, :readonly) }
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "relations" do
|
32
|
+
it { should have_one(:billing_address, as: Klarna::Checkout::Address) }
|
33
|
+
it { should have_one(:shipping_address, as: Klarna::Checkout::Address) }
|
34
|
+
it { should have_one(:cart, as: Klarna::Checkout::Cart) }
|
35
|
+
it { should have_one(:customer, as: Klarna::Checkout::Customer) }
|
36
|
+
it { should have_one(:merchant, as: Klarna::Checkout::Merchant) }
|
37
|
+
it { should have_one(:gui, as: Klarna::Checkout::Gui) }
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "#as_json" do
|
41
|
+
let(:order) do
|
42
|
+
described_class.new \
|
43
|
+
merchant_reference: 'foo',
|
44
|
+
purchase_country: 'NO',
|
45
|
+
purchase_currency: 'NOK',
|
46
|
+
locale: 'nb-no',
|
47
|
+
cart: {
|
48
|
+
items: [{
|
49
|
+
reference: '1123581220325',
|
50
|
+
name: 'Widget',
|
51
|
+
quantity: 1,
|
52
|
+
unit_price: 666,
|
53
|
+
tax_rate: 2500
|
54
|
+
}]
|
55
|
+
},
|
56
|
+
merchant: {
|
57
|
+
id: '666666',
|
58
|
+
terms_uri: 'http://www.example.com/terms',
|
59
|
+
checkout_uri: 'http://www.example.com/checkout',
|
60
|
+
confirmation_uri: 'http://www.example.com/confirmation_uri',
|
61
|
+
push_uri: 'http://www.example.com/push'
|
62
|
+
}
|
63
|
+
end
|
64
|
+
|
65
|
+
let(:json_hash) { order.as_json }
|
66
|
+
subject do
|
67
|
+
json_hash
|
68
|
+
end
|
69
|
+
|
70
|
+
its([:merchant_reference]) { should eq 'foo' }
|
71
|
+
its([:purchase_country]) { should eq 'NO' }
|
72
|
+
its([:purchase_currency]) { should eq 'NOK' }
|
73
|
+
its([:locale]) { should eq 'nb-no' }
|
74
|
+
|
75
|
+
describe "cart/items/0" do
|
76
|
+
subject { json_hash[:cart][:items][0] }
|
77
|
+
|
78
|
+
its([:reference]) { should eq '1123581220325' }
|
79
|
+
its([:name]) { should eq 'Widget' }
|
80
|
+
its([:quantity]) { should eq 1 }
|
81
|
+
its([:unit_price]) { should eq 666 }
|
82
|
+
its([:tax_rate]) { should eq 2500 }
|
83
|
+
end
|
84
|
+
|
85
|
+
describe "merchant" do
|
86
|
+
subject { json_hash[:merchant] }
|
87
|
+
|
88
|
+
its([:id]) { should eq '666666' }
|
89
|
+
its([:terms_uri]) { should eq 'http://www.example.com/terms' }
|
90
|
+
its([:checkout_uri]) { should eq 'http://www.example.com/checkout' }
|
91
|
+
its([:confirmation_uri]) { should eq 'http://www.example.com/confirmation_uri' }
|
92
|
+
its([:push_uri]) { should eq 'http://www.example.com/push' }
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe "#to_json" do
|
97
|
+
it "bases it output on #as_json" do
|
98
|
+
subject.stub(:as_json) { { foo: "bar" } }
|
99
|
+
subject.to_json.should eq JSON.generate({ foo: "bar" })
|
100
|
+
|
101
|
+
subject.stub(:as_json) { { bar: "foo" } }
|
102
|
+
subject.to_json.should eq JSON.generate({ bar: "foo" })
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'klarna/checkout'
|
2
|
+
|
3
|
+
require 'webmock/rspec'
|
4
|
+
require 'vcr'
|
5
|
+
|
6
|
+
# require 'shoulda/matchers'
|
7
|
+
|
8
|
+
VCR.configure do |c|
|
9
|
+
c.cassette_library_dir = File.expand_path("../fixtures/vcr_cassettes", __FILE__)
|
10
|
+
c.hook_into :webmock # or :fakeweb
|
11
|
+
end
|
12
|
+
|
13
|
+
RSpec.configure do |config|
|
14
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
15
|
+
config.run_all_when_everything_filtered = true
|
16
|
+
|
17
|
+
config.filter_run :focus => true
|
18
|
+
config.mock_with :rspec
|
19
|
+
|
20
|
+
# config.order = "random"
|
21
|
+
end
|
22
|
+
|
23
|
+
Dir[File.expand_path("../shared/**/*.rb", __FILE__)].each { |f| require f }
|
24
|
+
Dir[File.expand_path("../support/**/*.rb", __FILE__)].each { |f| require f }
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'rspec/expectations'
|
2
|
+
|
3
|
+
RSpec::Matchers.define :have_attribute do |attr_name| # , type|
|
4
|
+
match do |subject|
|
5
|
+
attr_name = attr_name.to_s
|
6
|
+
|
7
|
+
subject.should respond_to("#{attr_name}")
|
8
|
+
subject.should respond_to("#{attr_name}=")
|
9
|
+
|
10
|
+
# case type
|
11
|
+
# when :readonly
|
12
|
+
# # expect {
|
13
|
+
# subject.public_send("#{attr_name}=")
|
14
|
+
# # }.to raise_error(NoMethodError)
|
15
|
+
# when :mandatory
|
16
|
+
# # subject.should validate_presence_of(attr_name)
|
17
|
+
# when :optional
|
18
|
+
# # subject.should_not validate_presence_of(attr_name)
|
19
|
+
# else
|
20
|
+
# raise "Please supply :readonly, :mandatory or :optional as second "+
|
21
|
+
# "argument to have_attribute matcher."
|
22
|
+
# end
|
23
|
+
|
24
|
+
# unless type == :readonly
|
25
|
+
# expect {
|
26
|
+
# subject.public_send("#{attr_name}=", 'new_value')
|
27
|
+
# }.to change(subject, attr_name).to('new_value')
|
28
|
+
# end
|
29
|
+
end
|
30
|
+
|
31
|
+
# failure_message_for_should do |klass|
|
32
|
+
# "expected #{klass.class.to_s} to have #{type.to_s} attribute #{attr_name}"
|
33
|
+
# end
|
34
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'rspec/expectations'
|
2
|
+
|
3
|
+
RSpec::Matchers.define :have_many do |attr_name, options|
|
4
|
+
match do |subject|
|
5
|
+
subject.should respond_to(attr_name)
|
6
|
+
subject.should respond_to("#{attr_name}=")
|
7
|
+
|
8
|
+
if options[:as]
|
9
|
+
subject.public_send("#{attr_name}=", [{}])
|
10
|
+
subject.public_send(attr_name).first.class.should eq options[:as]
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
failure_message_for_should do |klass|
|
15
|
+
"expected #{klass.inspect} to have has_many-association #{attr_name}"
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'rspec/expectations'
|
2
|
+
|
3
|
+
RSpec::Matchers.define :have_one do |attr_name, options|
|
4
|
+
match do |subject|
|
5
|
+
subject.should respond_to(attr_name)
|
6
|
+
subject.should respond_to("#{attr_name}=")
|
7
|
+
|
8
|
+
if options[:as]
|
9
|
+
subject.public_send("#{attr_name}=", {})
|
10
|
+
subject.public_send(attr_name).class.should eq options[:as]
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
failure_message_for_should do |klass|
|
15
|
+
"expected #{klass.inspect} to have has_one-association #{attr_name}"
|
16
|
+
end
|
17
|
+
end
|
metadata
ADDED
@@ -0,0 +1,230 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: klarna-checkout
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Theodor Tonum
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-02-04 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: faraday
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: activemodel
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.3'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.3'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: guard
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: guard-rspec
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - '>='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - '>='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: webmock
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - '>='
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: vcr
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - '>='
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - '>='
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: shoulda-matchers
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - '>='
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - '>='
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
description: Ruby Wrapper for Klarna Checkout Rest API
|
154
|
+
email:
|
155
|
+
- theodor@tonum.no
|
156
|
+
executables: []
|
157
|
+
extensions: []
|
158
|
+
extra_rdoc_files: []
|
159
|
+
files:
|
160
|
+
- .gitignore
|
161
|
+
- .rspec
|
162
|
+
- Gemfile
|
163
|
+
- Guardfile
|
164
|
+
- LICENSE.txt
|
165
|
+
- README.md
|
166
|
+
- Rakefile
|
167
|
+
- klarna-checkout.gemspec
|
168
|
+
- lib/klarna/checkout.rb
|
169
|
+
- lib/klarna/checkout/address.rb
|
170
|
+
- lib/klarna/checkout/cart.rb
|
171
|
+
- lib/klarna/checkout/cart_item.rb
|
172
|
+
- lib/klarna/checkout/client.rb
|
173
|
+
- lib/klarna/checkout/concerns/has_many.rb
|
174
|
+
- lib/klarna/checkout/concerns/has_one.rb
|
175
|
+
- lib/klarna/checkout/customer.rb
|
176
|
+
- lib/klarna/checkout/gui.rb
|
177
|
+
- lib/klarna/checkout/merchant.rb
|
178
|
+
- lib/klarna/checkout/order.rb
|
179
|
+
- lib/klarna/checkout/resource.rb
|
180
|
+
- lib/klarna/checkout/version.rb
|
181
|
+
- spec/acceptance/create_order_spec.rb
|
182
|
+
- spec/acceptance/read_order_spec.rb
|
183
|
+
- spec/fixtures/vcr_cassettes/create_order_spec.yml
|
184
|
+
- spec/fixtures/vcr_cassettes/read_order_spec.yml
|
185
|
+
- spec/lib/klarna/checkout/cart_spec.rb
|
186
|
+
- spec/lib/klarna/checkout/client_spec.rb
|
187
|
+
- spec/lib/klarna/checkout/order_spec.rb
|
188
|
+
- spec/lib/klarna/checkout/version_spec.rb
|
189
|
+
- spec/spec_helper.rb
|
190
|
+
- spec/support/matchers/have_attribute.rb
|
191
|
+
- spec/support/matchers/have_many.rb
|
192
|
+
- spec/support/matchers/have_one.rb
|
193
|
+
homepage: ''
|
194
|
+
licenses:
|
195
|
+
- MIT
|
196
|
+
metadata: {}
|
197
|
+
post_install_message:
|
198
|
+
rdoc_options: []
|
199
|
+
require_paths:
|
200
|
+
- lib
|
201
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
202
|
+
requirements:
|
203
|
+
- - '>='
|
204
|
+
- !ruby/object:Gem::Version
|
205
|
+
version: '0'
|
206
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
207
|
+
requirements:
|
208
|
+
- - '>='
|
209
|
+
- !ruby/object:Gem::Version
|
210
|
+
version: '0'
|
211
|
+
requirements: []
|
212
|
+
rubyforge_project:
|
213
|
+
rubygems_version: 2.1.5
|
214
|
+
signing_key:
|
215
|
+
specification_version: 4
|
216
|
+
summary: '...'
|
217
|
+
test_files:
|
218
|
+
- spec/acceptance/create_order_spec.rb
|
219
|
+
- spec/acceptance/read_order_spec.rb
|
220
|
+
- spec/fixtures/vcr_cassettes/create_order_spec.yml
|
221
|
+
- spec/fixtures/vcr_cassettes/read_order_spec.yml
|
222
|
+
- spec/lib/klarna/checkout/cart_spec.rb
|
223
|
+
- spec/lib/klarna/checkout/client_spec.rb
|
224
|
+
- spec/lib/klarna/checkout/order_spec.rb
|
225
|
+
- spec/lib/klarna/checkout/version_spec.rb
|
226
|
+
- spec/spec_helper.rb
|
227
|
+
- spec/support/matchers/have_attribute.rb
|
228
|
+
- spec/support/matchers/have_many.rb
|
229
|
+
- spec/support/matchers/have_one.rb
|
230
|
+
has_rdoc:
|